@@ -28,14 +28,58 @@ import ucrt
28
28
#endif
29
29
#endif
30
30
31
-
32
31
func decodeFromJSON< T: Decodable > ( json: UnsafeBufferPointer < UInt8 > ) throws -> T {
33
32
try withExtendedLifetime ( try JSONScanner . scan ( buffer: json) ) { map in
34
33
let decoder = JSONDecoding ( value: map. value, codingPathNode: . root)
35
34
return try T . init ( from: decoder)
36
35
}
37
36
}
38
37
38
+ /*
39
+ JSONMap is inspired by swift-foundation's JSONMap.
40
+
41
+ For JSON payload such as:
42
+
43
+ ```
44
+ {"array": [-1.3, true], "number": 42}
45
+ ```
46
+
47
+ will be scanned by 'JSONScanner' into a map like:
48
+
49
+ ```
50
+ <OM> == Object Marker
51
+ <AM> == Array Marker
52
+ <SS> == Simple String (a variant of String that can has no escapes and can be passed directly to a UTF-8 parser)
53
+ <NM> == Number Marker
54
+ <TL> == NULL Marker
55
+ map: [
56
+ 0: <OM>, -- object marker
57
+ 1: 15, | `- number of *map* elements in this collection
58
+ 2: <SS>, | --- key 1 '"array"'
59
+ 3: <int_ptr>, | | |- pointer in the payload
60
+ 4: 7, | | `- length
61
+ 5: <AM>, | --- value1 array
62
+ 6: 4, | | `- number of *map* elements in the array
63
+ 7: <NM>, | | -- arr elm 1 '-1.3'
64
+ 8: <int_ptr>, | | |
65
+ 9: 4, | | |
66
+ 10: <TL>, | | -- arr elm 2 'true'
67
+ 11: <SS>, | --- key 2 '"number"'
68
+ 12: <int_ptr>, | |
69
+ 13: 8, | |
70
+ 14: <NM> | --- value1: '42'
71
+ 15: <int_ptr>, | |
72
+ 16: 2, | |
73
+ ]
74
+ ```
75
+ To decode '<root>.number' value:
76
+ 1. Index 0 indicates it's a object.
77
+ 2. Parse a key string at index 2, which is not a match for "number"
78
+ 3. Skip the key's value by finding it's an array, then its 'index(afterValue:)' which is 11
79
+ 4. Parse a key string at index 11, matching "number"
80
+ 5. Parse a value number at the pointer of index 15, length at index 16
81
+ */
82
+
39
83
private struct JSONMap {
40
84
enum Descriptor : Int {
41
85
case nullKeyword // [desc]
@@ -47,15 +91,18 @@ private struct JSONMap {
47
91
case object // [desc, count, (key, value)...]
48
92
case array // [desc, count, element...]
49
93
}
94
+ typealias Data = [ Int ]
50
95
let data : [ Int ]
51
96
97
+ /// Top-level value.
52
98
var value : JSONMapValue {
53
99
JSONMapValue ( map: data [ ... ] )
54
100
}
55
101
}
56
102
103
+ /// Slice of JSONMap representing a single value.
57
104
private struct JSONMapValue {
58
- typealias Map = Array < Int > . SubSequence
105
+ typealias Map = JSONMap . Data . SubSequence
59
106
typealias Index = Map . Index
60
107
let map : Map
61
108
@@ -255,7 +302,7 @@ extension JSONMapValue {
255
302
extension JSONMapValue {
256
303
struct JSONArray : Collection {
257
304
typealias Index = JSONMapValue . Index
258
- var map : JSONMapValue
305
+ let map : JSONMapValue
259
306
260
307
var startIndex : Index { map. index ( offset: 2 ) }
261
308
var endIndex : Index { map. endIndex }
@@ -275,7 +322,7 @@ extension JSONMapValue {
275
322
}
276
323
277
324
struct ObjectIterator {
278
- var map : JSONMapValue
325
+ let map : JSONMapValue
279
326
var currIndex : Int
280
327
281
328
init ( map: JSONMapValue ) {
@@ -289,8 +336,7 @@ extension JSONMapValue {
289
336
return nil
290
337
}
291
338
let key = map. value ( at: currIndex)
292
- currIndex = key. endIndex
293
- let val = map. value ( at: currIndex)
339
+ let val = map. value ( at: key. endIndex)
294
340
currIndex = val. endIndex
295
341
return ( key, val)
296
342
}
0 commit comments