33// OpenSwiftUICore
44//
55// Audited for RELEASE_2024
6- // Status: WIP
6+ // Status: Complete
7+ // ID: FFA06CAF6B06DC3E21EC75547A0CD421
78
89import Foundation
910
@@ -15,7 +16,6 @@ package struct ProtobufDecoder {
1516 package typealias Field = ProtobufFormat . Field
1617 package typealias WireType = ProtobufFormat . WireType
1718
18-
1919 var data : NSData
2020 var ptr : UnsafeRawPointer
2121 var end : UnsafeRawPointer
@@ -35,5 +35,333 @@ package struct ProtobufDecoder {
3535}
3636
3737extension 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+ }
39367}
0 commit comments