@@ -2,176 +2,164 @@ import * as nodes from '../../../nodes';
22import { ClockDecoder } from '../../../../json-crdt-patch/codec/clock/ClockDecoder' ;
33import { ITimestampStruct , Timestamp } from '../../../../json-crdt-patch/clock' ;
44import { Model , UNDEFINED } from '../../../model/Model' ;
5- import { ORIGIN , SESSION } from '../../../../json-crdt-patch/constants' ;
6- import { Code } from '../../../../json-crdt-patch/codec/compact/constants ' ;
5+ import { JsonCrdtDataType , SESSION } from '../../../../json-crdt-patch/constants' ;
6+ import type * as t from './types ' ;
77
88export class Decoder {
99 protected time ?: number ;
1010 protected clockDecoder ?: ClockDecoder ;
1111
12- public decode ( data : unknown [ ] ) : Model {
13- const x = data [ 0 ] ;
14- const isServerTime = typeof x === 'number' ;
12+ public decode ( doc : t . JsonCrdtCompactDocument ) : Model {
13+ const [ time , root ] = doc ;
14+ const isServerTime = typeof time === 'number' ;
1515 if ( isServerTime ) {
16- this . time = x ;
16+ this . time = time ;
1717 } else {
18- this . clockDecoder = ClockDecoder . fromArr ( x as number [ ] ) ;
18+ this . clockDecoder = ClockDecoder . fromArr ( time as number [ ] ) ;
1919 }
20- const doc = isServerTime ? Model . withServerClock ( x as number ) : Model . withLogicalClock ( this . clockDecoder ! . clock ) ;
21- const val = data [ 1 ] ? this . decodeNode ( doc , data [ 1 ] ) : UNDEFINED ;
22- doc . root = new nodes . RootNode ( doc , val . id ) ;
23- return doc ;
20+ const model = isServerTime
21+ ? Model . withServerClock ( time as number )
22+ : Model . withLogicalClock ( this . clockDecoder ! . clock ) ;
23+ const val = root ? this . decNode ( model , root ) : UNDEFINED ;
24+ model . root = new nodes . RootNode ( model , val . id ) ;
25+ return model ;
2426 }
2527
26- protected ts ( arr : unknown [ ] , index : number ) : [ ITimestampStruct , number ] {
27- const x = arr [ index ] ;
28+ protected ts ( x : t . JsonCrdtCompactTimestamp ) : ITimestampStruct {
2829 if ( typeof x === 'number' ) {
29- if ( x < 0 ) {
30- const sessionIndex = - x ;
31- const timeDiff = arr [ index + 1 ] as number ;
32- return [ this . clockDecoder ! . decodeId ( sessionIndex , timeDiff ) , index + 2 ] ;
33- } else {
34- return [ new Timestamp ( SESSION . SERVER , this . time ! - x ) , index + 1 ] ;
35- }
30+ return new Timestamp ( SESSION . SERVER , this . time ! - x ) ;
3631 } else {
37- const time = ( x as [ number ] ) [ 0 ] ;
38- switch ( time ) {
39- case ORIGIN . time :
40- return [ ORIGIN , index + 1 ] ;
41- default :
42- return [ new Timestamp ( SESSION . SYSTEM , time ) , index + 1 ] ;
32+ const [ sid , time ] = x as [ number , number ] ;
33+ if ( sid < 0 ) {
34+ return this . clockDecoder ! . decodeId ( - sid , time ) ;
35+ } else {
36+ return new Timestamp ( sid , time ) ;
4337 }
4438 }
4539 }
4640
47- protected decodeNode ( doc : Model , data : unknown ) : nodes . JsonNode {
48- if ( data instanceof Array ) {
49- switch ( data [ 0 ] ) {
50- case Code . MakeObject :
51- return this . decodeObj ( doc , data ) ;
52- case Code . MakeArray :
53- return this . decodeArr ( doc , data ) ;
54- case Code . MakeString :
55- return this . decodeStr ( doc , data ) ;
56- case Code . MakeValue :
57- return this . decodeVal ( doc , data ) ;
58- case Code . MakeConst :
59- return this . decodeConst ( doc , data ) ;
60- case Code . MakeConstId :
61- return this . decodeConstId ( doc , data ) ;
62- case Code . MakeBinary :
63- return this . decodeBin ( doc , data ) ;
64- case Code . MakeTuple :
65- return this . decodeTup ( doc , data ) ;
66- }
41+ protected decNode ( model : Model , node : t . JsonCrdtCompactNode ) : nodes . JsonNode {
42+ switch ( node [ 0 ] ) {
43+ case JsonCrdtDataType . con :
44+ return this . decCon ( model , node ) ;
45+ case JsonCrdtDataType . val :
46+ return this . decVal ( model , node ) ;
47+ case JsonCrdtDataType . obj :
48+ return this . decObj ( model , node ) ;
49+ case JsonCrdtDataType . vec :
50+ return this . decVec ( model , node ) ;
51+ case JsonCrdtDataType . str :
52+ return this . decStr ( model , node ) ;
53+ case JsonCrdtDataType . bin :
54+ return this . decBin ( model , node ) ;
55+ case JsonCrdtDataType . arr :
56+ return this . decArr ( model , node ) ;
6757 }
6858 throw new Error ( 'UNKNOWN_NODE' ) ;
6959 }
7060
71- protected decodeObj ( doc : Model , data : unknown [ ] ) : nodes . ObjNode {
72- const [ id , index ] = this . ts ( data , 1 ) ;
73- const obj = new nodes . ObjNode ( doc , id ) ;
74- const length = data . length ;
75- for ( let i = index ; i < length ; ) {
76- const key = data [ i ] as string ;
77- const val = this . decodeNode ( doc , data [ ++ i ] ) ;
78- obj . put ( key , val . id ) ;
79- i ++ ;
61+ protected decCon ( doc : Model , node : t . JsonCrdtCompactCon ) : nodes . ConNode {
62+ const id = this . ts ( node [ 1 ] ) ;
63+ let data : unknown | undefined | Timestamp = node [ 2 ] ;
64+ if ( node . length > 3 ) {
65+ const specialData = node [ 3 ] as unknown ;
66+ if ( ! specialData ) data = undefined ;
67+ else data = this . ts ( specialData as t . JsonCrdtCompactTimestamp ) ;
8068 }
69+ const obj = new nodes . ConNode ( id , data ) ;
70+ doc . index . set ( id , obj ) ;
71+ return obj ;
72+ }
73+
74+ protected decVal ( doc : Model , node : t . JsonCrdtCompactVal ) : nodes . ValNode {
75+ const id = this . ts ( node [ 1 ] ) ;
76+ const child = this . decNode ( doc , node [ 2 ] ) ;
77+ const obj = new nodes . ValNode ( doc , id , child . id ) ;
8178 doc . index . set ( id , obj ) ;
8279 return obj ;
8380 }
8481
85- protected decodeTup ( doc : Model , data : unknown [ ] ) : nodes . VecNode {
86- const [ id , index ] = this . ts ( data , 1 ) ;
87- const obj = new nodes . VecNode ( doc , id ) ;
88- const length = data . length ;
82+ protected decObj ( model : Model , node : t . JsonCrdtCompactObj ) : nodes . ObjNode {
83+ const id = this . ts ( node [ 1 ] ) ;
84+ const obj = new nodes . ObjNode ( model , id ) ;
85+ const map = node [ 2 ] as t . JsonCrdtCompactObj [ 2 ] ;
86+ const keys = Object . keys ( map ) ;
87+ const length = keys . length ;
88+ for ( let i = 0 ; i < length ; i ++ ) {
89+ const key = keys [ i ] ;
90+ const val = this . decNode ( model , map [ key ] ) ;
91+ obj . put ( key , val . id ) ;
92+ }
93+ model . index . set ( id , obj ) ;
94+ return obj ;
95+ }
96+
97+ protected decVec ( model : Model , node : t . JsonCrdtCompactVec ) : nodes . VecNode {
98+ const id = this . ts ( node [ 1 ] ) ;
99+ const obj = new nodes . VecNode ( model , id ) ;
100+ const map = node [ 2 ] as t . JsonCrdtCompactVec [ 2 ] ;
89101 const elements = obj . elements ;
90- for ( let i = index ; i < length ; ) {
91- const component = data [ i ++ ] ;
92- if ( ! component ) elements . push ( undefined ) ;
102+ const length = map . length ;
103+ for ( let i = 0 ; i < length ; i ++ ) {
104+ const item = map [ i ] ;
105+ if ( ! item ) elements . push ( undefined ) ;
93106 else {
94- const node = this . decodeNode ( doc , component ) ;
95- elements . push ( node . id ) ;
107+ const child = this . decNode ( model , item ) ;
108+ elements . push ( child . id ) ;
96109 }
97110 }
98- doc . index . set ( id , obj ) ;
111+ model . index . set ( id , obj ) ;
99112 return obj ;
100113 }
101114
102- protected decodeArr ( doc : Model , data : unknown [ ] ) : nodes . ArrNode {
103- const size = data [ 1 ] as number ;
104- const [ id , index ] = this . ts ( data , 2 ) ;
105- const obj = new nodes . ArrNode ( doc , id ) ;
106- const self = this ;
107- let i = index ;
115+ protected decStr ( doc : Model , node : t . JsonCrdtCompactStr ) : nodes . StrNode {
116+ const id = this . ts ( node [ 1 ] ) ;
117+ const obj = new nodes . StrNode ( id ) ;
118+ const chunks = node [ 2 ] as t . JsonCrdtCompactStr [ 2 ] ;
119+ const size = chunks . length ;
120+ let i = 0 ;
108121 obj . ingest ( size , ( ) => {
109- const [ chunkId , idx ] = self . ts ( data , i ) ;
110- const content = data [ idx ] ;
111- i = idx + 1 ;
112- if ( typeof content === 'number' ) return new nodes . ArrChunk ( chunkId , content , undefined ) ;
113- const ids = ( content as unknown [ ] ) . map ( ( c ) => this . decodeNode ( doc , c ) . id ) ;
114- return new nodes . ArrChunk ( chunkId , ( content as string ) . length , ids ) ;
115- } ) ;
116- doc . index . set ( id , obj ) ;
117- return obj ;
118- }
119-
120- protected decodeStr ( doc : Model , data : unknown [ ] ) : nodes . StrNode {
121- const size = data [ 1 ] as number ;
122- const [ id , index ] = this . ts ( data , 2 ) ;
123- const node = new nodes . StrNode ( id ) ;
124- const self = this ;
125- let i = index ;
126- node . ingest ( size , ( ) => {
127- const [ chunkId , idx ] = self . ts ( data , i ) ;
128- const content = data [ idx ] ;
129- i = idx + 1 ;
122+ const chunk = chunks [ i ++ ] ;
123+ const chunkId = this . ts ( chunk [ 0 ] ) ;
124+ const content = chunk [ 1 ] ;
130125 if ( typeof content === 'number' ) return new nodes . StrChunk ( chunkId , content , '' ) ;
131126 return new nodes . StrChunk ( chunkId , ( content as string ) . length , content as string ) ;
132127 } ) ;
133- doc . index . set ( id , node ) ;
134- return node ;
135- }
136-
137- protected decodeBin ( doc : Model , data : unknown [ ] ) : nodes . BinNode {
138- const size = data [ 1 ] as number ;
139- const [ id , index ] = this . ts ( data , 2 ) ;
140- const node = new nodes . BinNode ( id ) ;
141- const self = this ;
142- let i = index ;
143- node . ingest ( size , ( ) => {
144- const [ chunkId , idx ] = self . ts ( data , i ) ;
145- const content = data [ idx ] ;
146- i = idx + 1 ;
147- if ( typeof content === 'number' ) return new nodes . BinChunk ( chunkId , content , undefined ) ;
148- const buf = content as Uint8Array ;
149- return new nodes . BinChunk ( chunkId , buf . length , buf ) ;
150- } ) ;
151- doc . index . set ( id , node ) ;
152- return node ;
153- }
154-
155- protected decodeVal ( doc : Model , data : unknown [ ] ) : nodes . ValNode {
156- const [ id , index ] = this . ts ( data , 1 ) ;
157- const child = this . decodeNode ( doc , data [ index ] ) ;
158- const obj = new nodes . ValNode ( doc , id , child . id ) ;
159128 doc . index . set ( id , obj ) ;
160129 return obj ;
161130 }
162131
163- protected decodeConst ( doc : Model , data : unknown [ ] ) : nodes . ConNode {
164- const [ id , index ] = this . ts ( data , 1 ) ;
165- const value = data [ index ] ;
166- const obj = new nodes . ConNode ( id , value ) ;
132+ protected decBin ( doc : Model , node : t . JsonCrdtCompactBin ) : nodes . BinNode {
133+ const id = this . ts ( node [ 1 ] ) ;
134+ const obj = new nodes . BinNode ( id ) ;
135+ const chunks = node [ 2 ] as t . JsonCrdtCompactBin [ 2 ] ;
136+ const size = chunks . length ;
137+ let i = 0 ;
138+ obj . ingest ( size , ( ) => {
139+ const chunk = chunks [ i ++ ] ;
140+ const chunkId = this . ts ( chunk [ 0 ] ) ;
141+ const content = chunk [ 1 ] ;
142+ if ( typeof content === 'number' ) return new nodes . BinChunk ( chunkId , content , undefined ) ;
143+ return new nodes . BinChunk ( chunkId , content . length , content ) ;
144+ } ) ;
167145 doc . index . set ( id , obj ) ;
168146 return obj ;
169147 }
170148
171- protected decodeConstId ( doc : Model , data : unknown [ ] ) : nodes . ConNode {
172- const [ id , index ] = this . ts ( data , 1 ) ;
173- const val = this . ts ( data , index ) [ 0 ] ;
174- const obj = new nodes . ConNode ( id , val ) ;
149+ protected decArr ( doc : Model , node : t . JsonCrdtCompactArr ) : nodes . ArrNode {
150+ const id = this . ts ( node [ 1 ] ) ;
151+ const obj = new nodes . ArrNode ( doc , id ) ;
152+ const chunks = node [ 2 ] as t . JsonCrdtCompactArr [ 2 ] ;
153+ const size = chunks . length ;
154+ let i = 0 ;
155+ obj . ingest ( size , ( ) => {
156+ const chunk = chunks [ i ++ ] ;
157+ const chunkId = this . ts ( chunk [ 0 ] ) ;
158+ const content = chunk [ 1 ] ;
159+ if ( typeof content === 'number' ) return new nodes . ArrChunk ( chunkId , content , undefined ) ;
160+ const ids = ( content as t . JsonCrdtCompactNode [ ] ) . map ( ( c ) => this . decNode ( doc , c ) . id ) ;
161+ return new nodes . ArrChunk ( chunkId , content . length , ids ) ;
162+ } ) ;
175163 doc . index . set ( id , obj ) ;
176164 return obj ;
177165 }
0 commit comments