@@ -3,6 +3,7 @@ import {ClockEncoder} from '../../../../json-crdt-patch/codec/clock/ClockEncoder
33import { ITimestampStruct , Timestamp } from '../../../../json-crdt-patch/clock' ;
44import { JsonCrdtDataType } from '../../../../json-crdt-patch/constants' ;
55import { SESSION } from '../../../../json-crdt-patch/constants' ;
6+ import type * as t from './types' ;
67import type { Model } from '../../../model' ;
78
89export class Encoder {
@@ -14,146 +15,120 @@ export class Encoder {
1415 this . model = model ;
1516 const isServerTime = model . clock . sid === SESSION . SERVER ;
1617 const clock = model . clock ;
17- const arr : unknown [ ] = isServerTime ? [ clock . time ] : [ null ] ;
1818 if ( isServerTime ) {
1919 this . time = clock . time ;
2020 } else {
2121 this . clock = new ClockEncoder ( ) ;
2222 this . clock . reset ( model . clock ) ;
2323 }
24- this . encodeRoot ( arr , model . root ) ;
25- if ( ! isServerTime ) arr [ 0 ] = this . clock ! . toJson ( ) ;
26- return arr ;
24+ const root = model . root ;
25+ const doc : t . JsonCrdtCompactDocument = [
26+ 0 ,
27+ ! root . val . time ? 0 : this . cNode ( root . node ( ) ) ,
28+ ] ;
29+ if ( ! isServerTime ) doc [ 0 ] = this . clock ! . toJson ( ) ;
30+ return doc ;
2731 }
2832
29- protected ts ( arr : unknown [ ] , ts : ITimestampStruct ) : void {
33+ protected ts ( ts : ITimestampStruct ) : t . JsonCrdtCompactTimestamp {
3034 switch ( ts . sid ) {
31- case SESSION . SYSTEM : {
32- arr . push ( [ ts . time ] ) ;
33- break ;
34- }
35- case SESSION . SERVER : {
36- arr . push ( this . time ! - ts . time ) ;
37- break ;
38- }
35+ case SESSION . SYSTEM : return [ ts . sid , ts . time ] ;
36+ case SESSION . SERVER : return this . time ! - ts . time ;
3937 default : {
4038 const relativeId = this . clock ! . append ( ts ) ;
41- arr . push ( - relativeId . sessionIndex , relativeId . timeDiff ) ;
39+ return [ - relativeId . sessionIndex , relativeId . timeDiff ] ;
4240 }
4341 }
4442 }
4543
46- protected encodeRoot ( arr : unknown [ ] , root : nodes . RootNode ) : void {
47- if ( ! root . val . time ) arr . push ( 0 ) ;
48- else this . cNode ( arr , root . node ( ) ) ;
49- }
50-
51- protected cNode ( arr : unknown [ ] , node : nodes . JsonNode ) : void {
44+ protected cNode ( node : nodes . JsonNode ) : t . JsonCrdtCompactNode {
5245 // TODO: PERF: use switch with `node.constructor`.
53- if ( node instanceof nodes . ObjNode ) return this . cObj ( arr , node ) ;
54- else if ( node instanceof nodes . ArrNode ) return this . cArr ( arr , node ) ;
55- else if ( node instanceof nodes . StrNode ) return this . cStr ( arr , node ) ;
56- else if ( node instanceof nodes . ValNode ) return this . cVal ( arr , node ) ;
57- else if ( node instanceof nodes . VecNode ) return this . cVec ( arr , node ) ;
58- else if ( node instanceof nodes . ConNode ) return this . cCon ( arr , node ) ;
59- else if ( node instanceof nodes . BinNode ) return this . cBin ( arr , node ) ;
46+ if ( node instanceof nodes . ObjNode ) return this . cObj ( node ) ;
47+ else if ( node instanceof nodes . ArrNode ) return this . cArr ( node ) ;
48+ else if ( node instanceof nodes . StrNode ) return this . cStr ( node ) ;
49+ else if ( node instanceof nodes . ValNode ) return this . cVal ( node ) ;
50+ else if ( node instanceof nodes . VecNode ) return this . cVec ( node ) ;
51+ else if ( node instanceof nodes . ConNode ) return this . cCon ( node ) ;
52+ else if ( node instanceof nodes . BinNode ) return this . cBin ( node ) ;
6053 throw new Error ( 'UNKNOWN_NODE' ) ;
6154 }
6255
63- protected cObj ( arr : unknown [ ] , obj : nodes . ObjNode ) : void {
64- const res : unknown [ ] = [ JsonCrdtDataType . obj ] ;
65- arr . push ( res ) ;
66- this . ts ( res , obj . id ) ;
67- obj . nodes ( ( node , key ) => {
68- res . push ( key ) ;
69- this . cNode ( res , node ) ;
70- } ) ;
56+ protected cObj ( obj : nodes . ObjNode ) : t . JsonCrdtCompactObj {
57+ const map : t . JsonCrdtCompactObj [ 2 ] = { } ;
58+ obj . nodes ( ( child , key ) => map [ key ] = this . cNode ( child ) ) ;
59+ const res : t . JsonCrdtCompactObj = [ JsonCrdtDataType . obj , this . ts ( obj . id ) , map ] ;
60+ return res ;
7161 }
7262
73- protected cVec ( arr : unknown [ ] , obj : nodes . VecNode ) : void {
74- const res : unknown [ ] = [ JsonCrdtDataType . vec ] ;
75- arr . push ( res ) ;
76- this . ts ( res , obj . id ) ;
77- const elements = obj . elements ;
63+ protected cVec ( vec : nodes . VecNode ) : t . JsonCrdtCompactVec {
64+ const elements = vec . elements ;
7865 const length = elements . length ;
7966 const index = this . model . index ;
67+ const map : t . JsonCrdtCompactVec [ 2 ] = [ ] ;
8068 for ( let i = 0 ; i < length ; i ++ ) {
8169 const elementId = elements [ i ] ;
82- if ( ! elementId ) res . push ( 0 ) ;
70+ if ( ! elementId ) map . push ( 0 ) ;
8371 else {
8472 const node = index . get ( elementId ) ! ;
85- this . cNode ( res , node ) ;
73+ map . push ( this . cNode ( node ) ) ;
8674 }
8775 }
76+ const res : t . JsonCrdtCompactVec = [ JsonCrdtDataType . vec , this . ts ( vec . id ) , map ] ;
77+ return res ;
8878 }
8979
90- protected cArr ( arr : unknown [ ] , obj : nodes . ArrNode ) : void {
91- const res : unknown [ ] = [ JsonCrdtDataType . arr , obj . size ( ) ] ;
92- arr . push ( res ) ;
93- this . ts ( res , obj . id ) ;
94- const iterator = obj . iterator ( ) ;
95- let chunk ;
96- while ( ( chunk = iterator ( ) ) ) this . cArrChunk ( res , chunk ) ;
97- }
98-
99- protected cArrChunk ( arr : unknown [ ] , chunk : nodes . ArrChunk ) : void {
100- this . ts ( arr , chunk . id ) ;
101- if ( chunk . del ) arr . push ( chunk . span ) ;
102- else {
103- const nodes : unknown [ ] = [ ] ;
104- const index = this . model . index ;
105- for ( const n of chunk . data ! ) this . cNode ( nodes , index . get ( n ) ! ) ;
106- arr . push ( nodes ) ;
80+ protected cArr ( node : nodes . ArrNode ) : t . JsonCrdtCompactArr {
81+ const chunks : t . JsonCrdtCompactArr [ 2 ] = [ ] ;
82+ const index = this . model . index ;
83+ for ( let chunk = node . first ( ) ; chunk ; chunk = node . next ( chunk ) ) {
84+ const deleted = chunk . del ;
85+ const span = chunk . span ;
86+ const chunkIdEncoded = this . ts ( chunk . id ) ;
87+ if ( deleted ) {
88+ chunks . push ( [ chunkIdEncoded , span ] ) ;
89+ } else {
90+ const nodeIds = chunk . data ! ;
91+ const nodes : t . JsonCrdtCompactArrChunk [ 1 ] = [ ] ;
92+ for ( let i = 0 ; i < span ; i ++ ) nodes . push ( this . cNode ( index . get ( nodeIds [ i ] ) ! ) ) ;
93+ chunks . push ( [ chunkIdEncoded , nodes ] ) ;
94+ }
10795 }
96+ const res : t . JsonCrdtCompactArr = [ JsonCrdtDataType . arr , this . ts ( node . id ) , chunks ] ;
97+ return res ;
10898 }
10999
110- protected cStr ( arr : unknown [ ] , obj : nodes . StrNode ) : void {
111- const res : unknown [ ] = [ JsonCrdtDataType . str , obj . size ( ) ] ;
112- arr . push ( res ) ;
113- this . ts ( res , obj . id ) ;
114- const iterator = obj . iterator ( ) ;
115- let chunk ;
116- while ( ( chunk = iterator ( ) ) ) this . cStrChunk ( res , chunk as nodes . StrChunk ) ;
117- }
118-
119- protected cStrChunk ( arr : unknown [ ] , chunk : nodes . StrChunk ) : void {
120- this . ts ( arr , chunk . id ) ;
121- arr . push ( chunk . del ? chunk . span : chunk . data ! ) ;
100+ protected cStr ( node : nodes . StrNode ) : t . JsonCrdtCompactStr {
101+ const chunks : t . JsonCrdtCompactStr [ 2 ] = [ ] ;
102+ for ( let chunk = node . first ( ) ; chunk ; chunk = node . next ( chunk ) )
103+ chunks . push ( [ this . ts ( chunk . id ) , chunk . del ? chunk . span : chunk . data ! ] as t . JsonCrdtCompactStrChunk | t . JsonCrdtCompactTombstone ) ;
104+ const res : t . JsonCrdtCompactStr = [ JsonCrdtDataType . str , this . ts ( node . id ) , chunks ] ;
105+ return res ;
122106 }
123107
124- protected cBin ( arr : unknown [ ] , obj : nodes . BinNode ) : void {
125- const res : unknown [ ] = [ JsonCrdtDataType . bin , obj . size ( ) ] ;
126- arr . push ( res ) ;
127- this . ts ( res , obj . id ) ;
128- const iterator = obj . iterator ( ) ;
129- let chunk ;
130- while ( ( chunk = iterator ( ) ) ) this . cBinChunk ( res , chunk as nodes . BinChunk ) ;
108+ protected cBin ( node : nodes . BinNode ) : t . JsonCrdtCompactBin {
109+ const chunks : t . JsonCrdtCompactBin [ 2 ] = [ ] ;
110+ for ( let chunk = node . first ( ) ; chunk ; chunk = node . next ( chunk ) )
111+ chunks . push ( [ this . ts ( chunk . id ) , chunk . del ? chunk . span : chunk . data ! ] as t . JsonCrdtCompactBinChunk | t . JsonCrdtCompactTombstone ) ;
112+ const res : t . JsonCrdtCompactBin = [ JsonCrdtDataType . bin , this . ts ( node . id ) , chunks ] ;
113+ return res ;
131114 }
132115
133- protected cBinChunk ( arr : unknown [ ] , chunk : nodes . BinChunk ) : void {
134- this . ts ( arr , chunk . id ) ;
135- arr . push ( chunk . del ? chunk . span : chunk . data ! ) ;
116+ protected cVal ( node : nodes . ValNode ) : t . JsonCrdtCompactVal {
117+ const res : t . JsonCrdtCompactVal = [ JsonCrdtDataType . val , this . ts ( node . id ) , this . cNode ( node . node ( ) ) ] ;
118+ return res ;
136119 }
137120
138- protected cVal ( arr : unknown [ ] , obj : nodes . ValNode ) : void {
139- const res : unknown [ ] = [ JsonCrdtDataType . val ] ;
140- arr . push ( res ) ;
141- this . ts ( res , obj . id ) ;
142- this . cNode ( res , obj . node ( ) ) ;
143- }
144-
145- protected cCon ( arr : unknown [ ] , obj : nodes . ConNode ) : void {
146- const val = obj . val ;
147- const res : unknown [ ] = [ ] ;
121+ protected cCon ( node : nodes . ConNode ) : t . JsonCrdtCompactCon {
122+ const val = node . val ;
123+ const res : t . JsonCrdtCompactCon = [ JsonCrdtDataType . con , this . ts ( node . id ) , val ] ;
148124 if ( val instanceof Timestamp ) {
149- res . push ( JsonCrdtDataType . con + 10 ) ;
150- this . ts ( res , obj . id ) ;
151- this . ts ( res , val ) ;
152- } else {
153- res . push ( JsonCrdtDataType . con ) ;
154- this . ts ( res , obj . id ) ;
155- if ( val !== undefined ) res . push ( val ) ;
125+ res [ 2 ] = 0 ;
126+ const specialData = this . ts ( val ) ;
127+ res . push ( specialData ) ;
128+ } else if ( val === undefined ) {
129+ res [ 2 ] = 0 ;
130+ res . push ( 0 ) ;
156131 }
157- arr . push ( res ) ;
132+ return res ;
158133 }
159134}
0 commit comments