Skip to content

Commit a48acbe

Browse files
committed
Creating Bytes from JSONValue with a Pointer
1 parent 59d69a7 commit a48acbe

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

0 commit comments

Comments
 (0)