3
3
// OpenSwiftUICore
4
4
//
5
5
// Audited for RELEASE_2024
6
- // Status: WIP
6
+ // Status: Complete
7
+ // ID: FFA06CAF6B06DC3E21EC75547A0CD421
7
8
8
9
import Foundation
9
10
@@ -15,7 +16,6 @@ package struct ProtobufDecoder {
15
16
package typealias Field = ProtobufFormat . Field
16
17
package typealias WireType = ProtobufFormat . WireType
17
18
18
-
19
19
var data : NSData
20
20
var ptr : UnsafeRawPointer
21
21
var end : UnsafeRawPointer
@@ -35,5 +35,333 @@ package struct ProtobufDecoder {
35
35
}
36
36
37
37
extension ProtobufDecoder {
38
- // TODO: Implement decoding methods
38
+ package mutating func nextField( ) throws -> ProtobufDecoder . Field ? {
39
+ guard ptr < end else {
40
+ packedField = Field ( rawValue: 0 )
41
+ return nil
42
+ }
43
+ if packedField. rawValue != 0 {
44
+ if ptr < packedEnd {
45
+ return packedField
46
+ } else if packedEnd < ptr {
47
+ throw DecodingError . failed
48
+ }
49
+ }
50
+ let result = try decodeVariant ( )
51
+ let field = Field ( rawValue: result)
52
+ guard field. tag > 0 else {
53
+ throw DecodingError . failed
54
+ }
55
+ return field
56
+ }
57
+
58
+ package mutating func skipField( _ field: ProtobufDecoder . Field ) throws {
59
+ switch field. wireType {
60
+ case . varint:
61
+ _ = try decodeVariant ( )
62
+ case . fixed64:
63
+ let newPtr = ptr. advanced ( by: 8 )
64
+ guard newPtr <= end else {
65
+ return
66
+ }
67
+ ptr = newPtr
68
+ case . lengthDelimited:
69
+ _ = try decodeDataBuffer ( )
70
+ case . fixed32:
71
+ let newPtr = ptr. advanced ( by: 4 )
72
+ guard newPtr <= end else {
73
+ return
74
+ }
75
+ ptr = newPtr
76
+ default :
77
+ throw DecodingError . failed
78
+ }
79
+ }
80
+
81
+ package mutating func boolField( _ field: ProtobufDecoder . Field ) throws -> Bool {
82
+ switch field. wireType {
83
+ case . varint:
84
+ break
85
+ case . lengthDelimited:
86
+ let offset = try decodeVariant ( )
87
+ let offsetPtr = ptr. advanced ( by: Int ( offset) )
88
+ guard offsetPtr <= end else {
89
+ throw DecodingError . failed
90
+ }
91
+ packedField = Field ( field. tag, wireType: . varint)
92
+ packedEnd = offsetPtr
93
+ default :
94
+ throw DecodingError . failed
95
+ }
96
+ return try decodeVariant ( ) != 0
97
+ }
98
+
99
+ package mutating func uintField( _ field: ProtobufDecoder . Field ) throws -> UInt {
100
+ switch field. wireType {
101
+ case . varint:
102
+ break
103
+ case . lengthDelimited:
104
+ let offset = try decodeVariant ( )
105
+ let offsetPtr = ptr. advanced ( by: Int ( offset) )
106
+ guard offsetPtr <= end else {
107
+ throw DecodingError . failed
108
+ }
109
+ packedField = Field ( field. tag, wireType: . varint)
110
+ packedEnd = offsetPtr
111
+ default :
112
+ throw DecodingError . failed
113
+ }
114
+ return try decodeVariant ( )
115
+ }
116
+
117
+ package mutating func enumField< T> ( _ field: ProtobufDecoder . Field ) throws -> T ? where T: ProtobufEnum {
118
+ try T ( protobufValue: uintField ( field) )
119
+ }
120
+
121
+ package mutating func uint8Field( _ field: ProtobufDecoder . Field ) throws -> UInt8 {
122
+ try UInt8 ( uintField ( field) )
123
+ }
124
+
125
+ package mutating func uint16Field( _ field: ProtobufDecoder . Field ) throws -> UInt16 {
126
+ try UInt16 ( uintField ( field) )
127
+ }
128
+
129
+ package mutating func uint32Field( _ field: ProtobufDecoder . Field ) throws -> UInt32 {
130
+ try UInt32 ( uintField ( field) )
131
+ }
132
+
133
+ package mutating func uint64Field( _ field: ProtobufDecoder . Field ) throws -> UInt64 {
134
+ try UInt64 ( uintField ( field) )
135
+ }
136
+
137
+ package mutating func intField( _ field: ProtobufDecoder . Field ) throws -> Int {
138
+ let value = Int ( bitPattern: try uintField ( field) )
139
+ return Int ( bitPattern: UInt ( bitPattern: ( value >> 1 ) ) ^ UInt ( bitPattern: - ( value & 1 ) ) )
140
+ }
141
+
142
+ package mutating func fixed32Field( _ field: ProtobufDecoder . Field ) throws -> UInt32 {
143
+ switch field. wireType {
144
+ case . lengthDelimited:
145
+ let offset = try decodeVariant ( )
146
+ let offsetPtr = ptr. advanced ( by: Int ( offset) )
147
+ guard offsetPtr <= end else {
148
+ throw DecodingError . failed
149
+ }
150
+ packedField = Field ( field. tag, wireType: . fixed32)
151
+ packedEnd = offsetPtr
152
+ case . fixed32:
153
+ break
154
+ default :
155
+ throw DecodingError . failed
156
+ }
157
+ let newPtr = ptr. advanced ( by: 4 )
158
+ guard newPtr <= end else {
159
+ throw DecodingError . failed
160
+ }
161
+ let value = ptr. loadUnaligned ( as: UInt32 . self)
162
+ ptr = newPtr
163
+ return value
164
+ }
165
+
166
+ package mutating func fixed64Field( _ field: ProtobufDecoder . Field ) throws -> UInt64 {
167
+ switch field. wireType {
168
+ case . lengthDelimited:
169
+ let offset = try decodeVariant ( )
170
+ let offsetPtr = ptr. advanced ( by: Int ( offset) )
171
+ guard offsetPtr <= end else {
172
+ throw DecodingError . failed
173
+ }
174
+ packedField = Field ( field. tag, wireType: . fixed64)
175
+ packedEnd = offsetPtr
176
+ case . fixed64:
177
+ break
178
+ default :
179
+ throw DecodingError . failed
180
+ }
181
+ let newPtr = ptr. advanced ( by: 8 )
182
+ guard newPtr <= end else {
183
+ throw DecodingError . failed
184
+ }
185
+ let value = ptr. loadUnaligned ( as: UInt64 . self)
186
+ ptr = newPtr
187
+ return value
188
+ }
189
+
190
+ package mutating func floatField( _ field: ProtobufDecoder . Field ) throws -> Float {
191
+ switch field. wireType {
192
+ case . lengthDelimited:
193
+ let offset = try decodeVariant ( )
194
+ let offsetPtr = ptr. advanced ( by: Int ( offset) )
195
+ guard offsetPtr <= end else {
196
+ throw DecodingError . failed
197
+ }
198
+ packedField = Field ( field. tag, wireType: . fixed32)
199
+ packedEnd = offsetPtr
200
+ case . fixed32:
201
+ break
202
+ default :
203
+ throw DecodingError . failed
204
+ }
205
+ let newPtr = ptr. advanced ( by: 4 )
206
+ guard newPtr <= end else {
207
+ throw DecodingError . failed
208
+ }
209
+ let value = ptr. loadUnaligned ( as: UInt32 . self)
210
+ ptr = newPtr
211
+ return Float ( bitPattern: value)
212
+ }
213
+
214
+ package mutating func doubleField( _ field: ProtobufDecoder . Field ) throws -> Double {
215
+ switch field. wireType {
216
+ case . fixed64:
217
+ break
218
+ case . lengthDelimited:
219
+ let offset = try decodeVariant ( )
220
+ let offsetPtr = ptr. advanced ( by: Int ( offset) )
221
+ guard offsetPtr <= end else {
222
+ throw DecodingError . failed
223
+ }
224
+ packedField = Field ( field. tag, wireType: . fixed64)
225
+ packedEnd = offsetPtr
226
+ case . fixed32:
227
+ let newPtr = ptr. advanced ( by: 4 )
228
+ guard newPtr <= end else {
229
+ throw DecodingError . failed
230
+ }
231
+ let value = ptr. loadUnaligned ( as: UInt32 . self)
232
+ ptr = newPtr
233
+ return Double ( Float ( bitPattern: value) )
234
+ default :
235
+ throw DecodingError . failed
236
+ }
237
+ let newPtr = ptr. advanced ( by: 8 )
238
+ guard newPtr <= end else {
239
+ throw DecodingError . failed
240
+ }
241
+ let value = ptr. loadUnaligned ( as: UInt64 . self)
242
+ ptr = newPtr
243
+ return Double ( bitPattern: value)
244
+ }
245
+
246
+ @inline ( __always)
247
+ package mutating func cgFloatField( _ field: ProtobufDecoder . Field ) throws -> CGFloat {
248
+ try doubleField ( field)
249
+ }
250
+
251
+ package mutating func dataBufferField( _ field: ProtobufDecoder . Field ) throws -> UnsafeRawBufferPointer {
252
+ switch field. wireType {
253
+ case . lengthDelimited:
254
+ try decodeDataBuffer ( )
255
+ default :
256
+ throw DecodingError . failed
257
+ }
258
+ }
259
+
260
+ package mutating func dataField( _ field: ProtobufDecoder . Field ) throws -> Data {
261
+ switch field. wireType {
262
+ case . lengthDelimited:
263
+ let buffer = try decodeDataBuffer ( )
264
+ guard let baseAddress = buffer. baseAddress else {
265
+ return Data ( )
266
+ }
267
+ let startIndex = baseAddress - data. bytes
268
+ let endIndex = startIndex + buffer. count
269
+ return ( data as Data ) [ startIndex..< endIndex]
270
+ default :
271
+ throw DecodingError . failed
272
+ }
273
+ }
274
+
275
+ package mutating func messageField< T> ( _ field: ProtobufDecoder . Field ) throws -> T where T: ProtobufDecodableMessage {
276
+ guard field. wireType == . lengthDelimited else {
277
+ throw DecodingError . failed
278
+ }
279
+ return try decodeMessage ( )
280
+ }
281
+
282
+ package mutating func messageField< T> ( _ field: ProtobufDecoder . Field , _ body: ( inout ProtobufDecoder ) throws -> T ) throws -> T {
283
+ guard field. wireType == . lengthDelimited else {
284
+ throw DecodingError . failed
285
+ }
286
+ return try decodeMessage ( body)
287
+ }
288
+
289
+ package mutating func stringField( _ field: ProtobufDecoder . Field ) throws -> String {
290
+ let data = try dataField ( field)
291
+ guard let result = String ( data: data, encoding: . utf8) else {
292
+ throw DecodingError . failed
293
+ }
294
+ return result
295
+ }
296
+
297
+ package mutating func codableField< T> ( _ field: ProtobufDecoder . Field ) throws -> T where T: Decodable {
298
+ let data = try dataField ( field)
299
+ return try value ( fromBinaryPlist: data)
300
+ }
301
+ }
302
+
303
+ extension ProtobufDecoder {
304
+ private mutating func decodeVariant( ) throws -> UInt {
305
+ var value : UInt = 0
306
+ var shift : UInt = 0
307
+ var shouldContinue = false
308
+ repeat {
309
+ guard ptr < end else {
310
+ throw DecodingError . failed
311
+ }
312
+ let byte = ptr. loadUnaligned ( as: UInt8 . self)
313
+ ptr += 1
314
+ value |= UInt ( byte & 0x7f ) << shift
315
+ shift += 7
316
+ shouldContinue = ( byte & 0x80 != 0 )
317
+ } while shouldContinue
318
+ return value
319
+ }
320
+
321
+ private mutating func decodeDataBuffer( ) throws -> UnsafeRawBufferPointer {
322
+ let count = try Int ( decodeVariant ( ) )
323
+ let oldPtr = ptr
324
+ let newPtr = ptr. advanced ( by: count)
325
+ guard newPtr <= end else {
326
+ throw DecodingError . failed
327
+ }
328
+ ptr = newPtr
329
+ return UnsafeRawBufferPointer ( start: oldPtr, count: count)
330
+ }
331
+
332
+ private mutating func beginMessage( ) throws {
333
+ stack. append ( end)
334
+ let count = try Int ( decodeVariant ( ) )
335
+ let newPtr = ptr. advanced ( by: count)
336
+ guard newPtr <= end else {
337
+ throw DecodingError . failed
338
+ }
339
+ end = newPtr
340
+ }
341
+
342
+ private mutating func decodeMessage< T> ( _ body: ( inout ProtobufDecoder ) throws -> T ) throws -> T {
343
+ try beginMessage ( )
344
+ defer { end = stack. removeLast ( ) }
345
+ return try body ( & self )
346
+ }
347
+
348
+ private mutating func decodeMessage< T> ( ) throws -> T where T: ProtobufDecodableMessage {
349
+ try beginMessage ( )
350
+ defer { end = stack. removeLast ( ) }
351
+ return try T ( from: & self )
352
+ }
353
+
354
+ func value< T> ( fromBinaryPlist data: Data , type: T . Type = T . self) throws -> T where T: Decodable {
355
+ #if os(WASI)
356
+ fatalError ( " PropertyListDecoder is not avaiable on WASI " )
357
+ #else
358
+ let decoder = PropertyListDecoder ( )
359
+ decoder. userInfo = userInfo
360
+ let resuls = try decoder. decode ( [ T ] . self, from: data)
361
+ guard let result = resuls. first else {
362
+ throw DecodingError . failed
363
+ }
364
+ return result
365
+ #endif
366
+ }
39
367
}
0 commit comments