@@ -95,7 +95,8 @@ func decodeFromJSON<T: Decodable>(json: UnsafeBufferPointer<UInt8>) throws -> T
9595private struct JSONMap {
9696 enum Descriptor : Int {
9797
98- // MARK: - Keywords; size:1 [desc]
98+ // MARK: - Keywords; mapSize:1 [desc]
99+ // desc: Descriptor.rawValue
99100
100101 /// 'null'
101102 case nullKeyword
@@ -104,7 +105,10 @@ private struct JSONMap {
104105 /// 'false' size:1
105106 case falseKeyword
106107
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.
108112
109113 /// Integer and floating number.
110114 case number
@@ -115,7 +119,10 @@ private struct JSONMap {
115119 /// String with escape sequences.
116120 case string
117121
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.
119126
120127 /// Object '{ ... }'. Elements are (key, value)...
121128 case object
@@ -140,18 +147,22 @@ private struct JSONMapBuilder {
140147 mapData. reserveCapacity ( 128 ) // 128 is good enough for most PluginMessage.
141148 }
142149
150+ /// Record .nullKeyword, .trueKeyword, or .falseKeyword.
143151 @inline ( __always)
144152 mutating func record( _ descriptor: JSONMap . Descriptor ) {
145153 mapData. append ( descriptor. rawValue)
146154 }
147155
156+ /// Record literal values i.e. numbers and strings, with a range in the source buffer.
148157 @inline ( __always)
149158 mutating func record( _ descriptor: JSONMap . Descriptor , range: Range < UnsafePointer < UInt8 > > ) {
150159 mapData. append ( descriptor. rawValue)
151160 mapData. append ( Int ( bitPattern: range. lowerBound) )
152161 mapData. append ( range. count)
153162 }
154163
164+ /// Record starting of a collection i.e. .array or .object. Must be paired with
165+ /// closeCollection(handle:) call using the returned handle.
155166 @inline ( __always)
156167 mutating func startCollection( _ descriptor: JSONMap . Descriptor ) -> Int {
157168 let handle = mapData. count
@@ -160,6 +171,7 @@ private struct JSONMapBuilder {
160171 return handle
161172 }
162173
174+ /// Close the collection. Accepts a "handle" returned from startCollection(_:).
163175 @inline ( __always)
164176 mutating func closeCollection( handle: Int ) {
165177 // 'handle': descriptor index.
@@ -172,11 +184,11 @@ private struct JSONMapBuilder {
172184 }
173185}
174186
175- enum JSONError : Error , CustomDebugStringConvertible {
187+ private enum JSONError : Error , CustomStringConvertible {
176188 case unexpectedEndOfFile
177189 case unexpectedCharacter( UInt8 , context: String )
178190
179- var debugDescription : String {
191+ var description : String {
180192 switch self {
181193 case . unexpectedEndOfFile:
182194 return " unexpected end of file "
@@ -245,7 +257,7 @@ private struct JSONScanner {
245257 }
246258
247259 @inline ( __always)
248- mutating func expect( _ char: UnicodeScalar ) throws {
260+ mutating func expect( ascii char: UnicodeScalar ) throws {
249261 guard hasData else {
250262 throw JSONError . unexpectedEndOfFile
251263 }
@@ -256,30 +268,30 @@ private struct JSONScanner {
256268 }
257269
258270 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 " )
262274 map. record ( . nullKeyword)
263275 }
264276
265277 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 " )
269281 map. record ( . trueKeyword)
270282 }
271283
272284 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 " )
277289 map. record ( . falseKeyword)
278290 }
279291
280292 mutating func scanString( start: Cursor ) throws {
281293 ptr = start
282- try expect ( " \" " )
294+ try expect ( ascii : " \" " )
283295
284296 var hasEscape = false
285297 var hasNonASCII = false
@@ -288,13 +300,16 @@ private struct JSONScanner {
288300 // FIXME: Error for invalid UTF8 sequences.
289301 if ptr. pointee == UInt8 ( ascii: " \\ " ) {
290302 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()
291306 _ = try advance ( )
292307 } else if ptr. pointee >= 0x80 {
293308 hasNonASCII = true
294309 }
295310 _ = try advance ( )
296311 }
297- try expect ( " \" " )
312+ try expect ( ascii : " \" " )
298313
299314 let kind : JSONMap . Descriptor
300315 if hasEscape {
@@ -308,6 +323,7 @@ private struct JSONScanner {
308323 }
309324
310325 mutating func scanNumber( start: Cursor ) throws {
326+ // FIXME: Error for invalid literal e.g. 'e-', '.e+'
311327 ptr = start
312328 _ = advance ( if: " - " )
313329 while advance ( if: " 0 " ... " 9 " ) { }
@@ -328,15 +344,15 @@ private struct JSONScanner {
328344 while hasData {
329345 try scanString ( start: ptr)
330346 skipWhitespace ( )
331- try expect ( " : " )
347+ try expect ( ascii : " : " )
332348 try scanValue ( )
333349 if advance ( if: " , " ) {
334350 skipWhitespace ( )
335351 continue
336352 }
337353 break
338354 }
339- try expect ( " } " )
355+ try expect ( ascii : " } " )
340356 }
341357 map. closeCollection ( handle: handle)
342358 }
@@ -353,7 +369,7 @@ private struct JSONScanner {
353369 }
354370 break
355371 }
356- try expect ( " ] " )
372+ try expect ( ascii : " ] " )
357373 }
358374 map. closeCollection ( handle: handle)
359375 }
@@ -459,8 +475,8 @@ private enum _JSONStringParser {
459475
460476 /// Decode a string value that includes escape sequences.
461477 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 )
464480
465481 // Decode 'source' UTF-8 JSON string literal into the uninitialized
466482 // UTF-8 buffer. Upon error, return 0 and make an empty string.
@@ -511,8 +527,8 @@ private enum _JSONStringParser {
511527 /// sequence, and call 'processCodeUnit' with the decoded value.
512528 /// Returns 'true' on error.
513529 ///
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.
516532 private static func decodeEscapeSequence(
517533 cursor: inout UnsafePointer < UInt8 > ,
518534 end: UnsafePointer < UInt8 > ,
@@ -608,9 +624,9 @@ private enum _JSONNumberParser {
608624 static func parseFloatingPoint< Floating: BinaryFloatingPoint > ( source: UnsafeBufferPointer < UInt8 > ) -> Floating ? {
609625 var endPtr : UnsafeMutablePointer < CChar > ? = nil
610626 let value : Floating ?
611- if ( Floating . self == Double . self) {
627+ if Floating . self == Double . self {
612628 value = Floating ( exactly: strtod ( source. baseAddress!, & endPtr) )
613- } else if ( Floating . self == Float . self) {
629+ } else if Floating . self == Float . self {
614630 value = Floating ( exactly: strtof ( source. baseAddress!, & endPtr) )
615631 } else {
616632 fatalError ( " unsupported floating point type " )
@@ -674,7 +690,8 @@ extension JSONMapValue {
674690 /// Returns true if this value represents a string and equals to 'str'.
675691 ///
676692 /// 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.
678695 func equals( to str: String ) -> Bool {
679696 if self . is ( . asciiSimpleString) {
680697 let lhs = valueBuffer ( )
@@ -794,7 +811,7 @@ private struct JSONDecoding {
794811// MARK: Pure decoding functions.
795812extension JSONDecoding {
796813 @inline ( __always)
797- static func _checkNotNull< T> (
814+ private static func _checkNotNull< T> (
798815 _ value: JSONMapValue ,
799816 expectedType: T . Type ,
800817 for codingPathNode: _CodingPathNode ,
@@ -830,6 +847,7 @@ extension JSONDecoding {
830847 )
831848 )
832849 }
850+
833851 @inline ( __always)
834852 static func _decode(
835853 _ value: JSONMapValue ,
@@ -839,6 +857,7 @@ extension JSONDecoding {
839857 ) throws -> Bool {
840858 try _unwrapOrThrow ( value. asBool ( ) , decoding: value, codingPathNode: codingPathNode, additionalKey)
841859 }
860+
842861 @inline ( __always)
843862 static func _decode(
844863 _ value: JSONMapValue ,
@@ -848,6 +867,7 @@ extension JSONDecoding {
848867 ) throws -> String {
849868 try _unwrapOrThrow ( value. asString ( ) , decoding: value, codingPathNode: codingPathNode, additionalKey)
850869 }
870+
851871 @inline ( __always)
852872 static func _decode< Integer: FixedWidthInteger > (
853873 _ value: JSONMapValue ,
@@ -857,6 +877,7 @@ extension JSONDecoding {
857877 ) throws -> Integer {
858878 try _unwrapOrThrow ( value. asInteger ( type) , decoding: value, codingPathNode: codingPathNode, additionalKey)
859879 }
880+
860881 @inline ( __always)
861882 static func _decode< Floating: BinaryFloatingPoint > (
862883 _ value: JSONMapValue ,
0 commit comments