1- import Foundation
21import SwiftOperators
32import SwiftParser
43
@@ -214,6 +213,93 @@ private final class PerSequenceFolder: SyntaxRewriter {
214213 }
215214}
216215
216+ /// Write directly to stderr without Foundation, whose output APIs would pull ICU into static builds.
217+ private func writeToStandardError( _ message: String ) {
218+ message. withCString { start in
219+ var pointer = UnsafeRawPointer ( start)
220+ let end = pointer. advanced ( by: strlen ( start) )
221+ while pointer != end {
222+ let written = write ( STDERR_FILENO, pointer, end - pointer)
223+ if written <= 0 {
224+ return
225+ }
226+ pointer = pointer. advanced ( by: written)
227+ }
228+ }
229+ }
230+
231+ private struct JSONEncodingError : Error , CustomStringConvertible {
232+ let type : Any . Type
233+
234+ var description : String {
235+ " unsupported JSON value of type \( String ( reflecting: type) ) "
236+ }
237+ }
238+
239+ private let hexDigits = Array ( " 0123456789abcdef " . utf8)
240+
241+ private func appendJSONString( _ string: String , to output: inout [ UInt8 ] ) {
242+ output. append ( UInt8 ( ascii: " \" " ) )
243+ for scalar in string. unicodeScalars {
244+ switch scalar. value {
245+ case 0x08 :
246+ output. append ( contentsOf: " \\ b " . utf8)
247+ case 0x09 :
248+ output. append ( contentsOf: " \\ t " . utf8)
249+ case 0x0a :
250+ output. append ( contentsOf: " \\ n " . utf8)
251+ case 0x0c :
252+ output. append ( contentsOf: " \\ f " . utf8)
253+ case 0x0d :
254+ output. append ( contentsOf: " \\ r " . utf8)
255+ case 0x22 :
256+ output. append ( contentsOf: " \\ \" " . utf8)
257+ case 0x2f :
258+ output. append ( contentsOf: " \\ / " . utf8)
259+ case 0x5c :
260+ output. append ( contentsOf: " \\ \\ " . utf8)
261+ case 0x00 ... 0x1f :
262+ output. append ( contentsOf: " \\ u00 " . utf8)
263+ output. append ( hexDigits [ Int ( scalar. value >> 4 ) ] )
264+ output. append ( hexDigits [ Int ( scalar. value & 0x0f ) ] )
265+ default :
266+ output. append ( contentsOf: String ( scalar) . utf8)
267+ }
268+ }
269+ output. append ( UInt8 ( ascii: " \" " ) )
270+ }
271+
272+ private func appendJSON( _ value: Any , to output: inout [ UInt8 ] ) throws {
273+ switch value {
274+ case let string as String :
275+ appendJSONString ( string, to: & output)
276+ case let integer as Int :
277+ output. append ( contentsOf: String ( integer) . utf8)
278+ case let array as [ Any ] :
279+ output. append ( UInt8 ( ascii: " [ " ) )
280+ for (index, element) in array. enumerated ( ) {
281+ if index != 0 {
282+ output. append ( UInt8 ( ascii: " , " ) )
283+ }
284+ try appendJSON ( element, to: & output)
285+ }
286+ output. append ( UInt8 ( ascii: " ] " ) )
287+ case let object as [ String : Any ] :
288+ output. append ( UInt8 ( ascii: " { " ) )
289+ for (index, key) in object. keys. sorted ( ) . enumerated ( ) {
290+ if index != 0 {
291+ output. append ( UInt8 ( ascii: " , " ) )
292+ }
293+ appendJSONString ( key, to: & output)
294+ output. append ( UInt8 ( ascii: " : " ) )
295+ try appendJSON ( object [ key] !, to: & output)
296+ }
297+ output. append ( UInt8 ( ascii: " } " ) )
298+ default :
299+ throw JSONEncodingError ( type: type ( of: value) )
300+ }
301+ }
302+
217303/// Parse the given NUL-terminated Swift source string and return a
218304/// heap-allocated, NUL-terminated JSON representation of the syntax tree.
219305///
@@ -231,13 +317,14 @@ public func ssr_parse_json(_ source: UnsafePointer<CChar>?) -> UnsafeMutablePoin
231317 let converter = SourceLocationConverter ( fileName: " <input> " , tree: tree)
232318 let json = serialize ( folded, converter)
233319
234- guard
235- let data = try ? JSONSerialization . data (
236- withJSONObject : json, options : [ . sortedKeys ] ) ,
237- let string = String ( data : data , encoding : . utf8 )
238- else {
320+ var bytes : [ UInt8 ] = [ ]
321+ do {
322+ try appendJSON ( json, to : & bytes )
323+ } catch {
324+ writeToStandardError ( " SwiftSyntaxFFI: JSON serialization failed: \( error ) \n " )
239325 return nil
240326 }
327+ let string = String ( decoding: bytes, as: UTF8 . self)
241328 return strdup ( string)
242329}
243330
0 commit comments