Skip to content

Commit ea7aa98

Browse files
committed
Creating Bytes from JSONValue with a Pointer
1 parent 834a28e commit ea7aa98

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

Sources/PureSwiftJSONParsing/JSONValue.swift

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,117 @@ public func == (lhs: JSONValue, rhs: JSONValue) -> Bool {
130130
return false
131131
}
132132
}
133+
134+
@available(*, deprecated, message: "Don't use this, this is slow")
135+
class WritableBuffer {
136+
private var ptr: UnsafeMutableRawBufferPointer
137+
138+
@usableFromInline typealias _Index = UInt32
139+
@usableFromInline typealias _Capacity = UInt32
140+
141+
@usableFromInline var _index : _Index = 0
142+
@usableFromInline var _capacity: _Capacity = 6144
143+
144+
init() {
145+
self.ptr = UnsafeMutableRawBufferPointer.allocate(byteCount: Int(_capacity), alignment: 0)
146+
}
147+
148+
@inline(__always) func write(_ ptr: UnsafeRawBufferPointer) {
149+
let bytesCount = ptr.count
150+
let target = UnsafeMutableRawBufferPointer(rebasing: self.ptr.dropFirst(Int(_index)))
151+
target.copyBytes(from: ptr)
152+
self._index += _Index(bytesCount)
153+
}
154+
155+
@inline(__always) func write(byte: UInt8) {
156+
self.ptr[Int(self._index)] = byte
157+
self._index += 1
158+
}
159+
160+
@inline(__always) func toBytes() -> [UInt8] {
161+
return [UInt8](ptr)
162+
}
163+
}
164+
165+
extension WritableBuffer {
166+
167+
func write(json: JSONValue) {
168+
169+
switch json {
170+
case .null:
171+
self.write(byte: UInt8(ascii: "n"))
172+
self.write(byte: UInt8(ascii: "u"))
173+
self.write(byte: UInt8(ascii: "l"))
174+
self.write(byte: UInt8(ascii: "l"))
175+
176+
case .bool(true):
177+
self.write(byte: UInt8(ascii: "t"))
178+
self.write(byte: UInt8(ascii: "r"))
179+
self.write(byte: UInt8(ascii: "u"))
180+
self.write(byte: UInt8(ascii: "e"))
181+
182+
case .bool(false):
183+
self.write(byte: UInt8(ascii: "f"))
184+
self.write(byte: UInt8(ascii: "a"))
185+
self.write(byte: UInt8(ascii: "l"))
186+
self.write(byte: UInt8(ascii: "s"))
187+
self.write(byte: UInt8(ascii: "e"))
188+
189+
case .string(let string):
190+
self.write(byte: UInt8(ascii: "\""))
191+
string.utf8.withContiguousStorageIfAvailable {
192+
self.write(UnsafeRawBufferPointer($0))
193+
}
194+
self.write(byte: UInt8(ascii: "\""))
195+
case .number(let string):
196+
string.utf8.withContiguousStorageIfAvailable {
197+
self.write(UnsafeRawBufferPointer($0))
198+
}
199+
case .array(let array):
200+
var iterator = array.makeIterator()
201+
self.write(byte: UInt8(ascii: "["))
202+
// we don't like branching, this is why we have this extra
203+
if let first = iterator.next() {
204+
self.write(json: first)
205+
}
206+
while let item = iterator.next() {
207+
self.write(byte: UInt8(ascii: ","))
208+
self.write(json: item)
209+
}
210+
self.write(byte: UInt8(ascii: "]"))
211+
case .object(let dict):
212+
var iterator = dict.makeIterator()
213+
self.write(byte: UInt8(ascii: "{"))
214+
if let (key, value) = iterator.next() {
215+
self.write(byte: UInt8(ascii: "\""))
216+
key.utf8.withContiguousStorageIfAvailable {
217+
self.write(UnsafeRawBufferPointer($0))
218+
}
219+
self.write(byte: UInt8(ascii: "\""))
220+
self.write(byte: UInt8(ascii: ":"))
221+
self.write(json: value)
222+
}
223+
while let (key, value) = iterator.next() {
224+
self.write(byte: UInt8(ascii: ","))
225+
self.write(byte: UInt8(ascii: "\""))
226+
key.utf8.withContiguousStorageIfAvailable {
227+
self.write(UnsafeRawBufferPointer($0))
228+
}
229+
self.write(byte: UInt8(ascii: "\""))
230+
self.write(byte: UInt8(ascii: ":"))
231+
self.write(json: value)
232+
}
233+
self.write(byte: UInt8(ascii: "}"))
234+
}
235+
}
236+
}
237+
238+
extension JSONValue {
239+
240+
@available(*, deprecated, message: "Don't use this, this is slow")
241+
public func toBytes() -> [UInt8] {
242+
let buffer = WritableBuffer()
243+
buffer.write(json: self)
244+
return buffer.toBytes()
245+
}
246+
}

0 commit comments

Comments
 (0)