@@ -55,6 +55,19 @@ fileprivate class InternPool {
5555 return immutable
5656 }
5757
58+ func intern( utf8Ptr: UnsafeBufferPointer < UInt8 > ) -> UnsafeRawBufferPointer {
59+ #if swift(>=4.1)
60+ let mutable = UnsafeMutableRawBufferPointer . allocate ( byteCount: utf8Ptr. count,
61+ alignment: MemoryLayout< UInt8> . alignment)
62+ #else
63+ let mutable = UnsafeMutableRawBufferPointer . allocate ( count: utf8. count)
64+ #endif
65+ mutable. copyBytes ( from: utf8Ptr)
66+ let immutable = UnsafeRawBufferPointer ( mutable)
67+ interned. append ( immutable)
68+ return immutable
69+ }
70+
5871 deinit {
5972 for buff in interned {
6073 #if swift(>=4.1)
@@ -91,10 +104,17 @@ public struct _NameMap: ExpressibleByDictionaryLiteral {
91104 /// has to be computed, it caches the UTF-8 bytes in an
92105 /// unmovable and immutable heap area.
93106 internal struct Name : Hashable , CustomStringConvertible {
94- // This is safe to use elsewhere in this library
95- internal init ( staticString: StaticString ) {
107+ // This should not be used outside of this file, as it requires
108+ // coordinating the lifecycle with the lifecycle of the pool
109+ // where the raw UTF8 gets interned.
110+ fileprivate init ( staticString: StaticString , pool: InternPool ) {
96111 self . nameString = . staticString( staticString)
97- self . utf8Buffer = UnsafeRawBufferPointer ( start: staticString. utf8Start, count: staticString. utf8CodeUnitCount)
112+ if staticString. hasPointerRepresentation {
113+ self . utf8Buffer = UnsafeRawBufferPointer ( start: staticString. utf8Start,
114+ count: staticString. utf8CodeUnitCount)
115+ } else {
116+ self . utf8Buffer = staticString. withUTF8Buffer { pool. intern ( utf8Ptr: $0) }
117+ }
98118 }
99119
100120 // This should not be used outside of this file, as it requires
@@ -202,14 +222,14 @@ public struct _NameMap: ExpressibleByDictionaryLiteral {
202222 switch description {
203223
204224 case . same( proto: let p) :
205- let protoName = Name ( staticString: p)
225+ let protoName = Name ( staticString: p, pool : internPool )
206226 let names = Names ( json: protoName, proto: protoName)
207227 numberToNameMap [ number] = names
208228 protoToNumberMap [ protoName] = number
209229 jsonToNumberMap [ protoName] = number
210230
211231 case . standard( proto: let p) :
212- let protoName = Name ( staticString: p)
232+ let protoName = Name ( staticString: p, pool : internPool )
213233 let jsonString = toJsonFieldName ( protoName. description)
214234 let jsonName = Name ( string: jsonString, pool: internPool)
215235 let names = Names ( json: jsonName, proto: protoName)
@@ -219,22 +239,22 @@ public struct _NameMap: ExpressibleByDictionaryLiteral {
219239 jsonToNumberMap [ jsonName] = number
220240
221241 case . unique( proto: let p, json: let j) :
222- let jsonName = Name ( staticString: j)
223- let protoName = Name ( staticString: p)
242+ let jsonName = Name ( staticString: j, pool : internPool )
243+ let protoName = Name ( staticString: p, pool : internPool )
224244 let names = Names ( json: jsonName, proto: protoName)
225245 numberToNameMap [ number] = names
226246 protoToNumberMap [ protoName] = number
227247 jsonToNumberMap [ protoName] = number
228248 jsonToNumberMap [ jsonName] = number
229249
230250 case . aliased( proto: let p, aliases: let aliases) :
231- let protoName = Name ( staticString: p)
251+ let protoName = Name ( staticString: p, pool : internPool )
232252 let names = Names ( json: protoName, proto: protoName)
233253 numberToNameMap [ number] = names
234254 protoToNumberMap [ protoName] = number
235255 jsonToNumberMap [ protoName] = number
236256 for alias in aliases {
237- let protoName = Name ( staticString: alias)
257+ let protoName = Name ( staticString: alias, pool : internPool )
238258 protoToNumberMap [ protoName] = number
239259 jsonToNumberMap [ protoName] = number
240260 }
0 commit comments