@@ -32,7 +32,7 @@ protocol ByteTreeScalarDecodable {
32
32
/// - size: The length of the serialized data in bytes
33
33
/// - Returns: The deserialized value
34
34
static func read( from pointer: UnsafeRawPointer , size: Int ,
35
- userInfo: [ ByteTreeUserInfoKey : Any ] ) -> Self
35
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] > ) -> Self
36
36
}
37
37
38
38
/// A type that can be deserialized from ByteTree into an object with child
@@ -48,32 +48,34 @@ protocol ByteTreeObjectDecodable {
48
48
/// - numFields: The number of fields that are present in the serialized
49
49
/// object
50
50
/// - Returns: The deserialized object
51
- static func read( from reader: ByteTreeObjectReader , numFields: Int ,
52
- userInfo: [ ByteTreeUserInfoKey : Any ] ) -> Self
51
+ static func read( from reader: UnsafeMutablePointer < ByteTreeObjectReader > ,
52
+ numFields: Int ,
53
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] > ) -> Self
53
54
}
54
55
55
56
// MARK: - Reader objects
56
57
57
58
/// Helper object for reading objects out a ByteTree. Keeps track that fields
58
59
/// are not read out of order and discards all trailing fields that were present
59
60
/// in the binary format but were not handled when reading the object.
60
- class ByteTreeObjectReader {
61
+ struct ByteTreeObjectReader {
61
62
/// The reader that holds a reference to the data from which the object is
62
63
/// read
63
- private let reader : ByteTreeReader
64
+ private let reader : UnsafeMutablePointer < ByteTreeReader >
64
65
65
66
/// The number of fields this object is expected to have
66
67
private let numFields : Int
67
68
68
69
/// The index of the field that is expected to be read next.
69
70
private var nextIndex : Int = 0
70
71
71
- fileprivate init ( reader: ByteTreeReader , numFields: Int ) {
72
+ fileprivate init ( reader: UnsafeMutablePointer < ByteTreeReader > ,
73
+ numFields: Int ) {
72
74
self . reader = reader
73
75
self . numFields = numFields
74
76
}
75
77
76
- private func advanceAndValidateIndex( _ index: Int ) {
78
+ private mutating func advanceAndValidateIndex( _ index: Int ) {
77
79
assert ( index == nextIndex, " Reading fields out of order " )
78
80
assert ( index < numFields)
79
81
nextIndex += 1
@@ -88,11 +90,11 @@ class ByteTreeObjectReader {
88
90
/// - objectType: The type as which this field should be read
89
91
/// - index: The index of this field
90
92
/// - Returns: The decoded field
91
- func readField< FieldType: ByteTreeScalarDecodable > (
93
+ mutating func readField< FieldType: ByteTreeScalarDecodable > (
92
94
_ objectType: FieldType . Type , index: Int
93
95
) -> FieldType {
94
96
advanceAndValidateIndex ( index)
95
- return reader. read ( objectType)
97
+ return reader. pointee . read ( objectType)
96
98
}
97
99
98
100
/// Read the field at the given index as the specified type. All indicies must
@@ -103,23 +105,23 @@ class ByteTreeObjectReader {
103
105
/// - objectType: The type as which this field should be read
104
106
/// - index: The index of this field
105
107
/// - Returns: The decoded field
106
- func readField< FieldType: ByteTreeObjectDecodable > (
108
+ mutating func readField< FieldType: ByteTreeObjectDecodable > (
107
109
_ objectType: FieldType . Type , index: Int
108
110
) -> FieldType {
109
111
advanceAndValidateIndex ( index)
110
- return reader. read ( objectType)
112
+ return reader. pointee . read ( objectType)
111
113
}
112
114
113
115
/// Read and immediately discard the field at the specified index. This
114
116
/// advances the reader by one field so that the next field can be read.
115
117
///
116
118
/// - Parameter index: The index of the field that shall be discarded
117
- func discardField( index: Int ) {
119
+ mutating func discardField( index: Int ) {
118
120
advanceAndValidateIndex ( index)
119
- reader. discardField ( )
121
+ reader. pointee . discardField ( )
120
122
}
121
123
122
- deinit {
124
+ fileprivate mutating func finalize ( ) {
123
125
// Discard all fields that have not been read
124
126
while nextIndex < numFields {
125
127
discardField ( index: nextIndex)
@@ -128,7 +130,7 @@ class ByteTreeObjectReader {
128
130
}
129
131
130
132
/// Reader for reading the ByteTree format into Swift objects
131
- class ByteTreeReader {
133
+ struct ByteTreeReader {
132
134
enum DeserializationError : Error , CustomStringConvertible {
133
135
case versionValidationFailed( ByteTreeReader . ProtocolVersion )
134
136
@@ -147,10 +149,10 @@ class ByteTreeReader {
147
149
/// A pointer pointing to the next byte of serialized data to be read
148
150
private var pointer : UnsafeRawPointer
149
151
150
- private var userInfo : [ ByteTreeUserInfoKey : Any ]
152
+ private var userInfo : UnsafePointer < [ ByteTreeUserInfoKey : Any ] >
151
153
152
154
private init ( pointer: UnsafeRawPointer ,
153
- userInfo: [ ByteTreeUserInfoKey : Any ] ) {
155
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] > ) {
154
156
self . pointer = pointer
155
157
self . userInfo = userInfo
156
158
}
@@ -170,10 +172,10 @@ class ByteTreeReader {
170
172
/// failed
171
173
static func read< T: ByteTreeObjectDecodable > (
172
174
_ rootObjectType: T . Type , from pointer: UnsafeRawPointer ,
173
- userInfo: [ ByteTreeUserInfoKey : Any ] ,
175
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] > ,
174
176
protocolVersionValidation: ( ProtocolVersion ) -> Bool
175
177
) throws -> T {
176
- let reader = ByteTreeReader ( pointer: pointer, userInfo: userInfo)
178
+ var reader = ByteTreeReader ( pointer: pointer, userInfo: userInfo)
177
179
try reader. readAndValidateProtocolVersion ( protocolVersionValidation)
178
180
return reader. read ( rootObjectType)
179
181
}
@@ -190,7 +192,7 @@ class ByteTreeReader {
190
192
/// - Returns: The deserialized tree
191
193
static func read< T: ByteTreeObjectDecodable > (
192
194
_ rootObjectType: T . Type , from data: Data ,
193
- userInfo: [ ByteTreeUserInfoKey : Any ] ,
195
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] > ,
194
196
protocolVersionValidation versionValidate: ( ProtocolVersion ) -> Bool
195
197
) throws -> T {
196
198
return try data. withUnsafeBytes { ( pointer: UnsafePointer < UInt8 > ) in
@@ -209,13 +211,13 @@ class ByteTreeReader {
209
211
///
210
212
/// - Parameter type: The type as which the current data should be read
211
213
/// - Returns: The read value
212
- private func readRaw< T> ( _ type: T . Type ) -> T {
214
+ private mutating func readRaw< T> ( _ type: T . Type ) -> T {
213
215
let result = pointer. bindMemory ( to: T . self, capacity: 1 ) . pointee
214
216
pointer = pointer. advanced ( by: MemoryLayout< T> . size)
215
217
return result
216
218
}
217
219
218
- private func readFieldLength( ) -> ( isObject: Bool , length: Int ) {
220
+ private mutating func readFieldLength( ) -> ( isObject: Bool , length: Int ) {
219
221
let raw = UInt32 ( littleEndian: readRaw ( UInt32 . self) )
220
222
let isObject = ( raw & ( UInt32 ( 1 ) << 31 ) ) != 0
221
223
let length = Int ( raw & ~ ( UInt32 ( 1 ) << 31 ) )
@@ -226,7 +228,7 @@ class ByteTreeReader {
226
228
/// Read the number of fields in an object.
227
229
///
228
230
/// - Returns: The number of fields in the following object
229
- private func readObjectLength( ) -> Int {
231
+ private mutating func readObjectLength( ) -> Int {
230
232
let ( isObject, length) = readFieldLength ( )
231
233
assert ( isObject)
232
234
return length
@@ -235,7 +237,7 @@ class ByteTreeReader {
235
237
/// Read the size of a scalar in bytes
236
238
///
237
239
/// - Returns: The size of the following scalar in bytes
238
- private func readScalarLength( ) -> Int {
240
+ private mutating func readScalarLength( ) -> Int {
239
241
let ( isObject, length) = readFieldLength ( )
240
242
assert ( !isObject)
241
243
return length
@@ -246,7 +248,7 @@ class ByteTreeReader {
246
248
///
247
249
/// - Parameter validationCallback: A callback that determines if the given
248
250
/// protocol version can be read
249
- private func readAndValidateProtocolVersion(
251
+ private mutating func readAndValidateProtocolVersion(
250
252
_ validationCallback: ( ProtocolVersion ) -> Bool
251
253
) throws {
252
254
let protocolVersion = ProtocolVersion ( littleEndian:
@@ -261,20 +263,24 @@ class ByteTreeReader {
261
263
///
262
264
/// - Parameter objectType: The type as which the next field shall be read
263
265
/// - Returns: The deserialized object
264
- fileprivate func read< T: ByteTreeObjectDecodable > (
266
+ fileprivate mutating func read< T: ByteTreeObjectDecodable > (
265
267
_ objectType: T . Type
266
268
) -> T {
267
269
let numFields = readObjectLength ( )
268
- let objectReader = ByteTreeObjectReader ( reader: self ,
270
+ var objectReader = ByteTreeObjectReader ( reader: & self ,
269
271
numFields: numFields)
270
- return T . read ( from: objectReader, numFields: numFields, userInfo: userInfo)
272
+ defer {
273
+ objectReader. finalize ( )
274
+ }
275
+ return T . read ( from: & objectReader, numFields: numFields,
276
+ userInfo: userInfo)
271
277
}
272
278
273
279
/// Read the next field in the tree as a scalar of the specified type.
274
280
///
275
281
/// - Parameter scalarType: The type as which the field shall be read
276
282
/// - Returns: The deserialized scalar
277
- fileprivate func read< T: ByteTreeScalarDecodable > (
283
+ fileprivate mutating func read< T: ByteTreeScalarDecodable > (
278
284
_ scalarType: T . Type
279
285
) -> T {
280
286
let fieldSize = readScalarLength ( )
@@ -285,7 +291,7 @@ class ByteTreeReader {
285
291
}
286
292
287
293
/// Discard the next scalar field, advancing the pointer to the next field
288
- fileprivate func discardField( ) {
294
+ fileprivate mutating func discardField( ) {
289
295
let ( isObject, length) = readFieldLength ( )
290
296
if isObject {
291
297
// Discard object by discarding all its objects
@@ -305,7 +311,7 @@ class ByteTreeReader {
305
311
// multiple types
306
312
extension ByteTreeScalarDecodable where Self : FixedWidthInteger {
307
313
static func read( from pointer: UnsafeRawPointer , size: Int ,
308
- userInfo: [ ByteTreeUserInfoKey : Any ]
314
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] >
309
315
) -> Self {
310
316
assert ( size == MemoryLayout< Self> . size)
311
317
return pointer. bindMemory ( to: Self . self, capacity: 1 ) . pointee
@@ -318,7 +324,8 @@ extension UInt32: ByteTreeScalarDecodable {}
318
324
319
325
extension String : ByteTreeScalarDecodable {
320
326
static func read( from pointer: UnsafeRawPointer , size: Int ,
321
- userInfo: [ ByteTreeUserInfoKey : Any ] ) -> String {
327
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] >
328
+ ) -> String {
322
329
let data = Data ( bytes: pointer, count: size)
323
330
return String ( data: data, encoding: . utf8) !
324
331
}
@@ -327,8 +334,9 @@ extension String: ByteTreeScalarDecodable {
327
334
extension Optional : ByteTreeObjectDecodable
328
335
where
329
336
Wrapped: ByteTreeObjectDecodable {
330
- static func read( from reader: ByteTreeObjectReader , numFields: Int ,
331
- userInfo: [ ByteTreeUserInfoKey : Any ]
337
+ static func read( from reader: UnsafeMutablePointer < ByteTreeObjectReader > ,
338
+ numFields: Int ,
339
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] >
332
340
) -> Optional < Wrapped > {
333
341
if numFields == 0 {
334
342
return nil
@@ -342,11 +350,12 @@ extension Optional: ByteTreeObjectDecodable
342
350
extension Array : ByteTreeObjectDecodable
343
351
where
344
352
Element: ByteTreeObjectDecodable {
345
- static func read( from reader: ByteTreeObjectReader , numFields: Int ,
346
- userInfo: [ ByteTreeUserInfoKey : Any ]
353
+ static func read( from reader: UnsafeMutablePointer < ByteTreeObjectReader > ,
354
+ numFields: Int ,
355
+ userInfo: UnsafePointer < [ ByteTreeUserInfoKey : Any ] >
347
356
) -> Array < Element > {
348
357
return ( 0 ..< numFields) . map {
349
- return reader. readField ( Element . self, index: $0)
358
+ return reader. pointee . readField ( Element . self, index: $0)
350
359
}
351
360
}
352
361
}
0 commit comments