@@ -95,7 +95,8 @@ func decodeFromJSON<T: Decodable>(json: UnsafeBufferPointer<UInt8>) throws -> T
95
95
private struct JSONMap {
96
96
enum Descriptor : Int {
97
97
98
- // MARK: - Keywords; size:1 [desc]
98
+ // MARK: - Keywords; mapSize:1 [desc]
99
+ // desc: Descriptor.rawValue
99
100
100
101
/// 'null'
101
102
case nullKeyword
@@ -104,7 +105,10 @@ private struct JSONMap {
104
105
/// 'false' size:1
105
106
case falseKeyword
106
107
107
- // MARK: - Scalar values; size:3 [desc, pointer, length]
108
+ // MARK: - Scalar values; mapSize:3 [desc, pointer, length]
109
+ // desc: Descriptor.rawValue
110
+ // pointer: pointer to the start of the value in the source UTF-8 JSON buffer.
111
+ // length: the length of the value in the source UTF-8 JSON buffer.
108
112
109
113
/// Integer and floating number.
110
114
case number
@@ -115,7 +119,10 @@ private struct JSONMap {
115
119
/// String with escape sequences.
116
120
case string
117
121
118
- // MARK: - Collections; size: 2 + variable [desc, size, element...]
122
+ // MARK: - Collections; mapSize: 2 + variable [desc, size, element...]
123
+ // desc: Descriptor.rawValue
124
+ // size: the map size this collection occupies.
125
+ // element * n: JSON values in this collection. For collections, sequence of key/value pairs.
119
126
120
127
/// Object '{ ... }'. Elements are (key, value)...
121
128
case object
@@ -140,18 +147,22 @@ private struct JSONMapBuilder {
140
147
mapData. reserveCapacity ( 128 ) // 128 is good enough for most PluginMessage.
141
148
}
142
149
150
+ /// Record .nullKeyword, .trueKeyword, or .falseKeyword.
143
151
@inline ( __always)
144
152
mutating func record( _ descriptor: JSONMap . Descriptor ) {
145
153
mapData. append ( descriptor. rawValue)
146
154
}
147
155
156
+ /// Record literal values i.e. numbers and strings, with a range in the source buffer.
148
157
@inline ( __always)
149
158
mutating func record( _ descriptor: JSONMap . Descriptor , range: Range < UnsafePointer < UInt8 > > ) {
150
159
mapData. append ( descriptor. rawValue)
151
160
mapData. append ( Int ( bitPattern: range. lowerBound) )
152
161
mapData. append ( range. count)
153
162
}
154
163
164
+ /// Record starting of a collection i.e. .array or .object. Must be paired with
165
+ /// closeCollection(handle:) call using the returned handle.
155
166
@inline ( __always)
156
167
mutating func startCollection( _ descriptor: JSONMap . Descriptor ) -> Int {
157
168
let handle = mapData. count
@@ -160,6 +171,7 @@ private struct JSONMapBuilder {
160
171
return handle
161
172
}
162
173
174
+ /// Close the collection. Accepts a "handle" returned from startCollection(_:).
163
175
@inline ( __always)
164
176
mutating func closeCollection( handle: Int ) {
165
177
// 'handle': descriptor index.
@@ -172,7 +184,7 @@ private struct JSONMapBuilder {
172
184
}
173
185
}
174
186
175
- enum JSONError : Error , CustomDebugStringConvertible {
187
+ private enum JSONError : Error , CustomDebugStringConvertible {
176
188
case unexpectedEndOfFile
177
189
case unexpectedCharacter( UInt8 , context: String )
178
190
@@ -245,7 +257,7 @@ private struct JSONScanner {
245
257
}
246
258
247
259
@inline ( __always)
248
- mutating func expect( _ char: UnicodeScalar ) throws {
260
+ mutating func expect( ascii char: UnicodeScalar ) throws {
249
261
guard hasData else {
250
262
throw JSONError . unexpectedEndOfFile
251
263
}
@@ -256,30 +268,30 @@ private struct JSONScanner {
256
268
}
257
269
258
270
mutating func scanNull( ) throws {
259
- try expect ( " u " )
260
- try expect ( " l " )
261
- try expect ( " l " )
271
+ try expect ( ascii : " u " )
272
+ try expect ( ascii : " l " )
273
+ try expect ( ascii : " l " )
262
274
map. record ( . nullKeyword)
263
275
}
264
276
265
277
mutating func scanTrue( ) throws {
266
- try expect ( " r " )
267
- try expect ( " u " )
268
- try expect ( " e " )
278
+ try expect ( ascii : " r " )
279
+ try expect ( ascii : " u " )
280
+ try expect ( ascii : " e " )
269
281
map. record ( . trueKeyword)
270
282
}
271
283
272
284
mutating func scanFalse( ) throws {
273
- try expect ( " a " )
274
- try expect ( " l " )
275
- try expect ( " s " )
276
- try expect ( " e " )
285
+ try expect ( ascii : " a " )
286
+ try expect ( ascii : " l " )
287
+ try expect ( ascii : " s " )
288
+ try expect ( ascii : " e " )
277
289
map. record ( . falseKeyword)
278
290
}
279
291
280
292
mutating func scanString( start: Cursor ) throws {
281
293
ptr = start
282
- try expect ( " \" " )
294
+ try expect ( ascii : " \" " )
283
295
284
296
var hasEscape = false
285
297
var hasNonASCII = false
@@ -288,13 +300,16 @@ private struct JSONScanner {
288
300
// FIXME: Error for invalid UTF8 sequences.
289
301
if ptr. pointee == UInt8 ( ascii: " \\ " ) {
290
302
hasEscape = true
303
+ // eat '\'. Rest of the escape sequence are all ASCII. We just skip them
304
+ // ignoring how many bytes are actually for the escape sequence. For
305
+ // decoding, they are revisited in _JSONStingDecoder.decodeStringWithEscapes()
291
306
_ = try advance ( )
292
307
} else if ptr. pointee >= 0x80 {
293
308
hasNonASCII = true
294
309
}
295
310
_ = try advance ( )
296
311
}
297
- try expect ( " \" " )
312
+ try expect ( ascii : " \" " )
298
313
299
314
let kind : JSONMap . Descriptor
300
315
if hasEscape {
@@ -308,6 +323,7 @@ private struct JSONScanner {
308
323
}
309
324
310
325
mutating func scanNumber( start: Cursor ) throws {
326
+ // FIXME: Error for invalid literal e.g. 'e-', '.e+'
311
327
ptr = start
312
328
_ = advance ( if: " - " )
313
329
while advance ( if: " 0 " ... " 9 " ) { }
@@ -328,15 +344,15 @@ private struct JSONScanner {
328
344
while hasData {
329
345
try scanString ( start: ptr)
330
346
skipWhitespace ( )
331
- try expect ( " : " )
347
+ try expect ( ascii : " : " )
332
348
try scanValue ( )
333
349
if advance ( if: " , " ) {
334
350
skipWhitespace ( )
335
351
continue
336
352
}
337
353
break
338
354
}
339
- try expect ( " } " )
355
+ try expect ( ascii : " } " )
340
356
}
341
357
map. closeCollection ( handle: handle)
342
358
}
@@ -353,7 +369,7 @@ private struct JSONScanner {
353
369
}
354
370
break
355
371
}
356
- try expect ( " ] " )
372
+ try expect ( ascii : " ] " )
357
373
}
358
374
map. closeCollection ( handle: handle)
359
375
}
@@ -459,8 +475,8 @@ private enum _JSONStringParser {
459
475
460
476
/// Decode a string value that includes escape sequences.
461
477
static func decodeStringWithEscapes( source: UnsafeBufferPointer < UInt8 > ) -> String ? {
462
- // JSON string with escape sequences must be 2 bytes or longer.
463
- assert ( source. count > 0 )
478
+ // JSON string with escape sequences must be== 0 2 bytes or longer.
479
+ assert ( ! source. isEmpty )
464
480
465
481
// Decode 'source' UTF-8 JSON string literal into the uninitialized
466
482
// UTF-8 buffer. Upon error, return 0 and make an empty string.
@@ -511,8 +527,8 @@ private enum _JSONStringParser {
511
527
/// sequence, and call 'processCodeUnit' with the decoded value.
512
528
/// Returns 'true' on error.
513
529
///
514
- /// NOTE : We don't report detailed errors for now because we only care
515
- /// well-formed payloads from the compiler.
530
+ /// - Note : We don't report detailed errors for now because we only care
531
+ /// well-formed payloads from the compiler.
516
532
private static func decodeEscapeSequence(
517
533
cursor: inout UnsafePointer < UInt8 > ,
518
534
end: UnsafePointer < UInt8 > ,
@@ -608,9 +624,9 @@ private enum _JSONNumberParser {
608
624
static func parseFloatingPoint< Floating: BinaryFloatingPoint > ( source: UnsafeBufferPointer < UInt8 > ) -> Floating ? {
609
625
var endPtr : UnsafeMutablePointer < CChar > ? = nil
610
626
let value : Floating ?
611
- if ( Floating . self == Double . self) {
627
+ if Floating . self == Double . self {
612
628
value = Floating ( exactly: strtod ( source. baseAddress!, & endPtr) )
613
- } else if ( Floating . self == Float . self) {
629
+ } else if Floating . self == Float . self {
614
630
value = Floating ( exactly: strtof ( source. baseAddress!, & endPtr) )
615
631
} else {
616
632
fatalError ( " unsupported floating point type " )
@@ -674,7 +690,8 @@ extension JSONMapValue {
674
690
/// Returns true if this value represents a string and equals to 'str'.
675
691
///
676
692
/// This is faster than 'value.asString() == str' because this doesn't
677
- /// instantiate 'Swift.String' unless there are escaped characters.
693
+ /// instantiate 'Swift.String' unless there are escaped characters or
694
+ /// non-ASCII characters.
678
695
func equals( to str: String ) -> Bool {
679
696
if self . is ( . asciiSimpleString) {
680
697
let lhs = valueBuffer ( )
@@ -794,7 +811,7 @@ private struct JSONDecoding {
794
811
// MARK: Pure decoding functions.
795
812
extension JSONDecoding {
796
813
@inline ( __always)
797
- static func _checkNotNull< T> (
814
+ private static func _checkNotNull< T> (
798
815
_ value: JSONMapValue ,
799
816
expectedType: T . Type ,
800
817
for codingPathNode: _CodingPathNode ,
@@ -830,6 +847,7 @@ extension JSONDecoding {
830
847
)
831
848
)
832
849
}
850
+
833
851
@inline ( __always)
834
852
static func _decode(
835
853
_ value: JSONMapValue ,
@@ -839,6 +857,7 @@ extension JSONDecoding {
839
857
) throws -> Bool {
840
858
try _unwrapOrThrow ( value. asBool ( ) , decoding: value, codingPathNode: codingPathNode, additionalKey)
841
859
}
860
+
842
861
@inline ( __always)
843
862
static func _decode(
844
863
_ value: JSONMapValue ,
@@ -848,6 +867,7 @@ extension JSONDecoding {
848
867
) throws -> String {
849
868
try _unwrapOrThrow ( value. asString ( ) , decoding: value, codingPathNode: codingPathNode, additionalKey)
850
869
}
870
+
851
871
@inline ( __always)
852
872
static func _decode< Integer: FixedWidthInteger > (
853
873
_ value: JSONMapValue ,
@@ -857,6 +877,7 @@ extension JSONDecoding {
857
877
) throws -> Integer {
858
878
try _unwrapOrThrow ( value. asInteger ( type) , decoding: value, codingPathNode: codingPathNode, additionalKey)
859
879
}
880
+
860
881
@inline ( __always)
861
882
static func _decode< Floating: BinaryFloatingPoint > (
862
883
_ value: JSONMapValue ,
0 commit comments