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