1
- import {
2
- ConNode ,
3
- JsonNode ,
4
- ValNode ,
5
- ArrNode ,
6
- ArrChunk ,
7
- BinNode ,
8
- BinChunk ,
9
- ObjNode ,
10
- StrNode ,
11
- StrChunk ,
12
- } from '../../../nodes' ;
1
+ import * as nodes from '../../../nodes' ;
13
2
import { ClockTable } from '../../../../json-crdt-patch/codec/clock/ClockTable' ;
14
3
import { CrdtReader } from '../../../../json-crdt-patch/util/binary/CrdtReader' ;
15
4
import { IndexedFields , FieldName , IndexedNodeFields } from './types' ;
16
5
import { ITimestampStruct , IVectorClock , Timestamp , VectorClock } from '../../../../json-crdt-patch/clock' ;
17
6
import { Model , UNDEFINED } from '../../../model/Model' ;
18
- import { MsgPackDecoderFast } from '../../../../json-pack/msgpack' ;
7
+ import { CborDecoderBase } from '../../../../json-pack/cbor/CborDecoderBase' ;
8
+ import { CRDT_MAJOR } from '../../structural/binary/constants' ;
19
9
20
10
export class Decoder {
21
- public readonly dec = new MsgPackDecoderFast < CrdtReader > ( new CrdtReader ( ) ) ;
11
+ public readonly dec : CborDecoderBase < CrdtReader > ;
22
12
protected doc ! : Model ;
23
13
protected clockTable ?: ClockTable ;
24
14
15
+ constructor ( reader ?: CrdtReader ) {
16
+ this . dec = new CborDecoderBase < CrdtReader > ( reader || new CrdtReader ( ) ) ;
17
+ }
18
+
25
19
public decode < M extends Model > (
26
20
fields : IndexedFields ,
27
21
ModelConstructor : new ( clock : IVectorClock ) => M = Model as unknown as new ( clock : IVectorClock ) => M ,
@@ -47,14 +41,17 @@ export class Decoder {
47
41
const rootValue = this . ts ( ) ;
48
42
doc . root . set ( rootValue ) ;
49
43
}
50
- const docIndex = doc . index ;
51
- for ( const field in fields ) {
44
+ const index = doc . index ;
45
+ const keys = Object . keys ( fields ) ;
46
+ const length = keys . length ;
47
+ for ( let i = 0 ; i < length ; i ++ ) {
48
+ const field = keys [ i ] ;
52
49
if ( field . length < 3 ) continue ; // Skip "c" and "r".
53
50
const arr = fields [ field as FieldName ] ;
54
51
const id = clockTable . parseField ( field as FieldName ) ;
55
52
reader . reset ( arr ) ;
56
53
const node = this . decodeNode ( id ) ;
57
- docIndex . set ( node . id , node ) ;
54
+ index . set ( id , node ) ;
58
55
}
59
56
return doc ;
60
57
}
@@ -64,107 +61,117 @@ export class Decoder {
64
61
return new Timestamp ( this . clockTable ! . byIdx [ sessionIndex ] . sid , timeDiff ) ;
65
62
}
66
63
67
- protected decodeNode ( id : ITimestampStruct ) : JsonNode {
64
+ protected decodeNode ( id : ITimestampStruct ) : nodes . JsonNode {
68
65
const reader = this . dec . reader ;
69
- const byte = reader . u8 ( ) ;
70
- if ( byte <= 0b10001111 ) return this . cObj ( id , byte & 0b1111 ) ;
71
- else if ( byte <= 0b10011111 ) return this . cArr ( id , byte & 0b1111 ) ;
72
- else if ( byte <= 0b10111111 ) return this . cStr ( id , byte & 0b11111 ) ;
73
- else {
74
- switch ( byte ) {
75
- case 0xc4 :
76
- return this . cBin ( id , reader . u8 ( ) ) ;
77
- case 0xc5 :
78
- return this . cBin ( id , reader . u16 ( ) ) ;
79
- case 0xc6 :
80
- return this . cBin ( id , reader . u32 ( ) ) ;
81
- case 0xd4 :
82
- return this . cConst ( id ) ;
83
- case 0xd5 :
84
- return new ConNode ( id , this . ts ( ) ) ;
85
- case 0xd6 :
86
- return this . cVal ( id ) ;
87
- case 0xde :
88
- return this . cObj ( id , reader . u16 ( ) ) ;
89
- case 0xdf :
90
- return this . cObj ( id , reader . u32 ( ) ) ;
91
- case 0xdc :
92
- return this . cArr ( id , reader . u16 ( ) ) ;
93
- case 0xdd :
94
- return this . cArr ( id , reader . u32 ( ) ) ;
95
- case 0xd9 :
96
- return this . cStr ( id , reader . u8 ( ) ) ;
97
- case 0xda :
98
- return this . cStr ( id , reader . u16 ( ) ) ;
99
- case 0xdb :
100
- return this . cStr ( id , reader . u32 ( ) ) ;
101
- }
66
+ const octet = reader . u8 ( ) ;
67
+ const major = octet >> 5 ;
68
+ const minor = octet & 0b11111 ;
69
+ const length = minor < 24 ? minor : minor === 24 ? reader . u8 ( ) : minor === 25 ? reader . u16 ( ) : reader . u32 ( ) ;
70
+ switch ( major ) {
71
+ case CRDT_MAJOR . CON :
72
+ return this . decodeCon ( id , length ) ;
73
+ case CRDT_MAJOR . VAL :
74
+ return this . decodeVal ( id ) ;
75
+ case CRDT_MAJOR . OBJ :
76
+ return this . decodeObj ( id , length ) ;
77
+ case CRDT_MAJOR . VEC :
78
+ return this . decodeVec ( id , length ) ;
79
+ case CRDT_MAJOR . STR :
80
+ return this . decodeStr ( id , length ) ;
81
+ case CRDT_MAJOR . BIN :
82
+ return this . decodeBin ( id , length ) ;
83
+ case CRDT_MAJOR . ARR :
84
+ return this . decodeArr ( id , length ) ;
102
85
}
103
-
104
86
return UNDEFINED ;
105
87
}
106
88
107
- public cConst ( id : ITimestampStruct ) : ConNode {
108
- const val = this . dec . val ( ) ;
109
- return new ConNode ( id , val ) ;
89
+ public decodeCon ( id : ITimestampStruct , length : number ) : nodes . ConNode {
90
+ const decoder = this . dec ;
91
+ const data = ! length ? decoder . val ( ) : this . ts ( ) ;
92
+ const node = new nodes . ConNode ( id , data ) ;
93
+ return node ;
110
94
}
111
95
112
- public cVal ( id : ITimestampStruct ) : ValNode {
96
+ public decodeVal ( id : ITimestampStruct ) : nodes . ValNode {
113
97
const val = this . ts ( ) ;
114
- return new ValNode ( this . doc , id , val ) ;
98
+ const node = new nodes . ValNode ( this . doc , id , val ) ;
99
+ return node ;
115
100
}
116
101
117
- public cObj ( id : ITimestampStruct , length : number ) : ObjNode {
102
+ public decodeObj ( id : ITimestampStruct , length : number ) : nodes . ObjNode {
118
103
const decoder = this . dec ;
119
- const obj = new ObjNode ( this . doc , id ) ;
104
+ const obj = new nodes . ObjNode ( this . doc , id ) ;
120
105
const keys = obj . keys ;
121
106
for ( let i = 0 ; i < length ; i ++ ) {
122
- const key = String ( decoder . val ( ) ) ;
107
+ const key = decoder . val ( ) + '' ;
123
108
const val = this . ts ( ) ;
124
109
keys . set ( key , val ) ;
125
110
}
126
111
return obj ;
127
112
}
128
113
129
- protected cStr ( id : ITimestampStruct , length : number ) : StrNode {
130
- const decoder = this . dec ;
131
- const node = new StrNode ( id ) ;
132
- node . ingest ( length , ( ) => {
133
- const chunkId = this . ts ( ) ;
134
- const val = decoder . val ( ) ;
135
- if ( typeof val === 'number' ) return new StrChunk ( chunkId , val , '' ) ;
136
- const data = String ( val ) ;
137
- return new StrChunk ( chunkId , data . length , data ) ;
138
- } ) ;
114
+ public decodeVec ( id : ITimestampStruct , length : number ) : nodes . VecNode {
115
+ const reader = this . dec . reader ;
116
+ const node = new nodes . VecNode ( this . doc , id ) ;
117
+ const elements = node . elements ;
118
+ for ( let i = 0 ; i < length ; i ++ ) {
119
+ const octet = reader . u8 ( ) ;
120
+ if ( ! octet ) elements . push ( undefined ) ;
121
+ else elements . push ( this . ts ( ) ) ;
122
+ }
139
123
return node ;
140
124
}
141
125
142
- protected cBin ( id : ITimestampStruct , length : number ) : BinNode {
143
- const decoder = this . dec ;
144
- const reader = decoder . reader ;
145
- const node = new BinNode ( id ) ;
146
- node . ingest ( length , ( ) => {
147
- const chunkId = this . ts ( ) ;
148
- const [ deleted , length ] = reader . b1vu28 ( ) ;
149
- if ( deleted ) return new BinChunk ( chunkId , length , undefined ) ;
150
- const data = reader . buf ( length ) ;
151
- return new BinChunk ( chunkId , length , data ) ;
152
- } ) ;
126
+ protected decodeStr ( id : ITimestampStruct , length : number ) : nodes . StrNode {
127
+ const node = new nodes . StrNode ( id ) ;
128
+ node . ingest ( length , this . decodeStrChunk ) ;
153
129
return node ;
154
130
}
155
131
156
- protected cArr ( id : ITimestampStruct , length : number ) : ArrNode {
132
+ private decodeStrChunk = ( ) : nodes . StrChunk => {
157
133
const decoder = this . dec ;
158
134
const reader = decoder . reader ;
159
- const node = new ArrNode ( this . doc , id ) ;
160
- node . ingest ( length , ( ) => {
161
- const chunkId = this . ts ( ) ;
162
- const [ deleted , length ] = reader . b1vu28 ( ) ;
163
- if ( deleted ) return new ArrChunk ( chunkId , length , undefined ) ;
164
- const data : ITimestampStruct [ ] = [ ] ;
165
- for ( let i = 0 ; i < length ; i ++ ) data . push ( this . ts ( ) ) ;
166
- return new ArrChunk ( chunkId , length , data ) ;
167
- } ) ;
135
+ const id = this . ts ( ) ;
136
+ const isTombstone = reader . uint8 [ reader . x ] === 0 ;
137
+ if ( isTombstone ) {
138
+ reader . x ++ ;
139
+ const length = reader . vu39 ( ) ;
140
+ return new nodes . StrChunk ( id , length , '' ) ;
141
+ }
142
+ const text : string = decoder . readAsStr ( ) as string ;
143
+ return new nodes . StrChunk ( id , text . length , text ) ;
144
+ } ;
145
+
146
+ protected decodeBin ( id : ITimestampStruct , length : number ) : nodes . BinNode {
147
+ const node = new nodes . BinNode ( id ) ;
148
+ node . ingest ( length , this . decodeBinChunk ) ;
149
+ return node ;
150
+ }
151
+
152
+ private decodeBinChunk = ( ) : nodes . BinChunk => {
153
+ const id = this . ts ( ) ;
154
+ const reader = this . dec . reader ;
155
+ const [ deleted , length ] = reader . b1vu56 ( ) ;
156
+ if ( deleted ) return new nodes . BinChunk ( id , length , undefined ) ;
157
+ else return new nodes . BinChunk ( id , length , reader . buf ( length ) ) ;
158
+ } ;
159
+
160
+ protected decodeArr ( id : ITimestampStruct , length : number ) : nodes . ArrNode {
161
+ const node = new nodes . ArrNode ( this . doc , id ) ;
162
+ node . ingest ( length , this . decodeArrChunk ) ;
168
163
return node ;
169
164
}
165
+
166
+ private decodeArrChunk = ( ) : nodes . ArrChunk => {
167
+ const id = this . ts ( ) ;
168
+ const reader = this . dec . reader ;
169
+ const [ deleted , length ] = reader . b1vu56 ( ) ;
170
+ if ( deleted ) return new nodes . ArrChunk ( id , length , undefined ) ;
171
+ else {
172
+ const data : ITimestampStruct [ ] = [ ] ;
173
+ for ( let i = 0 ; i < length ; i ++ ) data . push ( this . ts ( ) ) ;
174
+ return new nodes . ArrChunk ( id , length , data ) ;
175
+ }
176
+ } ;
170
177
}
0 commit comments