@muze-nl/od-jsontag 0.3.4 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/package.json +6 -4
- package/src/parse.mjs +631 -996
- package/src/serialize.mjs +219 -220
- package/src/symbols.mjs +0 -1
- package/src/jsontag.mjs +0 -61
package/src/serialize.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import JSONTag from '@muze-nl/jsontag';
|
|
2
2
|
import {source,isProxy, isChanged, getIndex, getBuffer, resultSet} from './symbols.mjs'
|
|
3
|
-
import * as odJSONTag from './jsontag.mjs'
|
|
4
3
|
|
|
5
4
|
// faststringify function for a fast parseable arraybuffer output
|
|
6
5
|
//
|
|
@@ -17,233 +16,233 @@ function stringToSAB(strData) {
|
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
export default function serialize(value, options={}) {
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
let resultArray = false
|
|
20
|
+
let references = new WeakMap()
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
22
|
+
if (options.meta) {
|
|
23
|
+
if (!options.meta.index) {
|
|
24
|
+
options.meta.index = {}
|
|
25
|
+
}
|
|
26
|
+
if (!options.meta.index.id) {
|
|
27
|
+
options.meta.index.id = new Map()
|
|
28
|
+
}
|
|
29
|
+
if (options.meta.resultArray) {
|
|
30
|
+
resultArray = options.meta.resultArray
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!resultArray) {
|
|
34
|
+
resultArray = value?.[resultSet]
|
|
35
|
+
}
|
|
36
|
+
if (!resultArray) {
|
|
37
|
+
resultArray = []
|
|
38
|
+
}
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
40
|
+
function stringifyValue(value, inarray=false, current) {
|
|
41
|
+
let prop
|
|
42
|
+
let typeString = JSONTag.getTypeString(value)
|
|
43
|
+
let type = JSONTag.getType(value)
|
|
44
|
+
switch (type) {
|
|
45
|
+
case 'string':
|
|
46
|
+
case 'decimal':
|
|
47
|
+
case 'money':
|
|
48
|
+
case 'link':
|
|
49
|
+
case 'text':
|
|
50
|
+
case 'blob':
|
|
51
|
+
case 'color':
|
|
52
|
+
case 'email':
|
|
53
|
+
case 'hash':
|
|
54
|
+
case 'duration':
|
|
55
|
+
case 'phone':
|
|
56
|
+
case 'url':
|
|
57
|
+
case 'uuid':
|
|
58
|
+
case 'date':
|
|
59
|
+
case 'time':
|
|
60
|
+
case 'datetime':
|
|
61
|
+
if (JSONTag.isNull(value)) {
|
|
62
|
+
value = 'null'
|
|
63
|
+
} else {
|
|
64
|
+
value = realJSON.stringify(''+value)
|
|
65
|
+
}
|
|
66
|
+
prop = typeString + value
|
|
67
|
+
break
|
|
68
|
+
case 'int':
|
|
69
|
+
case 'uint':
|
|
70
|
+
case 'int8':
|
|
71
|
+
case 'uint8':
|
|
72
|
+
case 'int16':
|
|
73
|
+
case 'uint16':
|
|
74
|
+
case 'int32':
|
|
75
|
+
case 'uint32':
|
|
76
|
+
case 'int64':
|
|
77
|
+
case 'uint64':
|
|
78
|
+
case 'float':
|
|
79
|
+
case 'float32':
|
|
80
|
+
case 'float64':
|
|
81
|
+
case 'timestamp':
|
|
82
|
+
case 'number':
|
|
83
|
+
case 'boolean':
|
|
84
|
+
if (JSONTag.isNull(value)) {
|
|
85
|
+
value = 'null'
|
|
86
|
+
} else {
|
|
87
|
+
value = realJSON.stringify(value)
|
|
88
|
+
}
|
|
89
|
+
prop = typeString + value
|
|
90
|
+
break
|
|
91
|
+
case 'array':
|
|
92
|
+
let entries = value.map(e => stringifyValue(e, true, current))
|
|
93
|
+
let mergedEntries = []
|
|
94
|
+
let previousIndex = null
|
|
95
|
+
let startSlice = null
|
|
96
|
+
entries.forEach(e => {
|
|
97
|
+
if (e[0]=='~') {
|
|
98
|
+
let currIndex = parseInt(e.substr(1))
|
|
99
|
+
if (startSlice && currIndex === (previousIndex + 1)) {
|
|
100
|
+
mergedEntries.pop()
|
|
101
|
+
mergedEntries.push('~' + startSlice + '-' + currIndex)
|
|
102
|
+
previousIndex = currIndex
|
|
103
|
+
} else {
|
|
104
|
+
mergedEntries.push(e)
|
|
105
|
+
previousIndex = currIndex
|
|
106
|
+
startSlice = currIndex
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
mergedEntries.push(e)
|
|
110
|
+
previousIndex = null
|
|
111
|
+
startSlice = null
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
entries = mergedEntries.join(',')
|
|
115
|
+
prop = typeString + '[' + entries + ']'
|
|
116
|
+
break
|
|
117
|
+
case 'object':
|
|
118
|
+
if (!value) {
|
|
119
|
+
prop = 'null'
|
|
120
|
+
} else if (value[isProxy]) {
|
|
121
|
+
if (inarray) {
|
|
122
|
+
prop = '~'+value[getIndex]
|
|
123
|
+
} else {
|
|
124
|
+
prop = decoder.decode(value[getBuffer](current))
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
if (!references.has(value)) {
|
|
128
|
+
references.set(value, resultArray.length)
|
|
129
|
+
resultArray.push(value)
|
|
130
|
+
}
|
|
131
|
+
prop = '~'+references.get(value)
|
|
132
|
+
}
|
|
133
|
+
break
|
|
134
|
+
default:
|
|
135
|
+
throw new Error(JSONTag.getType(value)+' type not yet implemented')
|
|
136
|
+
break
|
|
137
|
+
}
|
|
138
|
+
return prop
|
|
139
|
+
}
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
const encoder = new TextEncoder()
|
|
142
|
+
const decoder = new TextDecoder()
|
|
144
143
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
// is only ever called on object values
|
|
145
|
+
// and should always return a stringified object, not a reference (~n)
|
|
146
|
+
const innerStringify = (current) => {
|
|
147
|
+
let object = resultArray[current]
|
|
148
|
+
let result
|
|
150
149
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
150
|
+
// if value is a valueProxy, just copy the input slice
|
|
151
|
+
if (object && !JSONTag.isNull(object) && object[isProxy] && !object[isChanged]) {
|
|
152
|
+
return decoder.decode(object[getBuffer](current))
|
|
153
|
+
}
|
|
154
|
+
if (typeof object === 'undefined' || object === null) {
|
|
155
|
+
return 'null'
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let props = []
|
|
159
|
+
for (let key of Object.getOwnPropertyNames(object)) {
|
|
160
|
+
let value = object[key]
|
|
161
|
+
let prop = stringifyValue(value, false, current)
|
|
162
|
+
let enumerable = object.propertyIsEnumerable(key) ? '' : '#'
|
|
163
|
+
props.push(enumerable+realJSON.stringify(key)+':'+prop) //FIXME: how does key get escaped?
|
|
164
|
+
}
|
|
165
|
+
result = JSONTag.getTypeString(object)+'{'+props.join(',')+'}'
|
|
166
|
+
return result
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const encode = (s) => {
|
|
170
|
+
if (typeof s == 'string' || s instanceof String) {
|
|
171
|
+
s = encoder.encode(s)
|
|
172
|
+
}
|
|
173
|
+
if (s[0]==43 || options.skipLength) {
|
|
174
|
+
return new Uint8Array(s)
|
|
175
|
+
}
|
|
176
|
+
let length = encoder.encode('('+s.length+')')
|
|
177
|
+
let u8arr = new Uint8Array(length.length+s.length)
|
|
178
|
+
u8arr.set(length, 0)
|
|
179
|
+
u8arr.set(s, length.length)
|
|
180
|
+
return u8arr
|
|
181
|
+
}
|
|
183
182
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
183
|
+
if (!value?.[resultSet]) {
|
|
184
|
+
resultArray.push(value)
|
|
185
|
+
}
|
|
186
|
+
let currentSource = 0
|
|
187
|
+
let currentResult = 0
|
|
188
|
+
let skipCount = 0
|
|
189
|
+
let result = []
|
|
190
|
+
while(currentSource<resultArray.length) {
|
|
191
|
+
if (!resultArray[currentSource]) {
|
|
192
|
+
//FIXME: should not happen, this means that there is no complete
|
|
193
|
+
//od-jsontag file, only patches?
|
|
194
|
+
skipCount++
|
|
195
|
+
} else if (resultArray[currentSource][isChanged] || !resultArray[currentSource][isProxy]) {
|
|
196
|
+
if (skipCount) {
|
|
197
|
+
result[currentResult] = encoder.encode('+'+skipCount)
|
|
198
|
+
skipCount = 0
|
|
199
|
+
currentResult++
|
|
200
|
+
}
|
|
201
|
+
result[currentResult] = encoder.encode(innerStringify(currentSource))
|
|
202
|
+
if (options.meta) {
|
|
203
|
+
const id=JSONTag.getAttribute(resultArray[currentSource],'id')
|
|
204
|
+
if (id) {
|
|
205
|
+
options.meta.index.id.set(id, currentSource)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
currentResult++
|
|
209
|
+
} else if (!options.changes) {
|
|
210
|
+
result[currentResult] = resultArray[currentSource][getBuffer](currentSource)
|
|
211
|
+
if (options.meta) {
|
|
212
|
+
const id=JSONTag.getAttribute(resultArray[currentSource],'id')
|
|
213
|
+
if (id) {
|
|
214
|
+
options.meta.index.id.set(id, currentSource)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
currentResult++
|
|
218
|
+
} else {
|
|
219
|
+
skipCount++
|
|
220
|
+
}
|
|
222
221
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
222
|
+
currentSource++
|
|
223
|
+
}
|
|
224
|
+
let arr = result.map(encode)
|
|
225
|
+
let length = 0
|
|
226
|
+
for (let line of arr) {
|
|
227
|
+
length += line.length+1
|
|
228
|
+
}
|
|
229
|
+
if (length) {
|
|
230
|
+
length -= 1 // skip last newline
|
|
231
|
+
}
|
|
232
|
+
let sab = new SharedArrayBuffer(length)
|
|
233
|
+
let u8arr = new Uint8Array(sab)
|
|
234
|
+
let offset = 0
|
|
235
|
+
for(let line of arr) {
|
|
236
|
+
u8arr.set(line, offset)
|
|
237
|
+
offset+=line.length
|
|
238
|
+
if (offset<length) {
|
|
239
|
+
u8arr.set([10], offset)
|
|
240
|
+
offset++
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return u8arr
|
|
245
244
|
}
|
|
246
245
|
|
|
247
246
|
export function stringify(buf) {
|
|
248
|
-
|
|
247
|
+
return decoder.decode(buf)
|
|
249
248
|
}
|
package/src/symbols.mjs
CHANGED
|
@@ -5,7 +5,6 @@ export const getBuffer = Symbol('getBuffer')
|
|
|
5
5
|
export const getIndex = Symbol('getIndex')
|
|
6
6
|
export const isChanged = Symbol('isChanged')
|
|
7
7
|
export const isParsed = Symbol('isParsed')
|
|
8
|
-
export const isReceived = Symbol('isReceived')
|
|
9
8
|
export const getString = Symbol('getString')
|
|
10
9
|
export const position = Symbol('position')
|
|
11
10
|
export const parent = Symbol('parent')
|
package/src/jsontag.mjs
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import JSONTag from '@muze-nl/jsontag'
|
|
2
|
-
import {source, isChanged} from './symbols.mjs'
|
|
3
|
-
|
|
4
|
-
export function getType(obj) {
|
|
5
|
-
return JSONTag.getType(obj?.[source] ?? obj)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function getAttribute(obj, attr) {
|
|
9
|
-
return JSONTag.getAttribute(obj?.[source] ?? obj, attr)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function getAttributes(obj) {
|
|
13
|
-
return JSONTag.getAttributes(obj?.[source] ?? obj)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function getAttributeString(obj) {
|
|
17
|
-
return JSONTag.getAttributesString(obj?.[source] ?? obj)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function getTypeString(obj) {
|
|
21
|
-
return JSONTag.getTypeString(obj?.[source] ?? obj)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function isNull(obj) {
|
|
25
|
-
return JSONTag.isNull(obj?.[source] ?? obj)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function setAttribute(obj, attr, value) {
|
|
29
|
-
if (obj?.[source]) {
|
|
30
|
-
obj[isChanged] = true
|
|
31
|
-
}
|
|
32
|
-
return JSONTag.setAttribute(obj?.[source] ?? obj, attr, value)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function setAttributes(obj, attr) {
|
|
36
|
-
if (obj?.[source]) {
|
|
37
|
-
obj[isChanged] = true
|
|
38
|
-
}
|
|
39
|
-
return JSONTag.setAttribute(obj?.[source] ?? obj, attr)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function setType(obj, type) {
|
|
43
|
-
if (obj?.[source]) {
|
|
44
|
-
obj[isChanged] = true
|
|
45
|
-
}
|
|
46
|
-
return JSONTag.setType(obj?.[source] ?? obj, type)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function addAttribute(obj, attr, value) {
|
|
50
|
-
if (obj?.[source]) {
|
|
51
|
-
obj[isChanged] = true
|
|
52
|
-
}
|
|
53
|
-
return JSONTag.addAttribute(obj?.[source] ?? obj, attr, value)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function removeAttribute(obj, attr) {
|
|
57
|
-
if (obj?.[source]) {
|
|
58
|
-
obj[isChanged] = true
|
|
59
|
-
}
|
|
60
|
-
return JSONTag.removeAttribute(obj?.[source] ?? obj, attr)
|
|
61
|
-
}
|