@@ -122,24 +122,17 @@ internal extension TLVDecoder {
122122
123123 func container < Key: CodingKey > ( keyedBy type: Key . Type ) throws -> KeyedDecodingContainer < Key > {
124124
125- log ? ( " Requested container keyed by \( type) for path \" \( codingPath. path) \" " )
125+ log ? ( " Requested container keyed by \( String ( reflecting : type) ) for path \" \( codingPath. path) \" " )
126126
127127 let container = self . stack. top
128128
129129 switch container {
130-
131130 case let . items( items) :
132-
133131 let keyedContainer = TLVKeyedDecodingContainer < Key > ( referencing: self , wrapping: items)
134-
135132 return KeyedDecodingContainer ( keyedContainer)
136-
137133 case let . item( item) :
138-
139134 let items = try decode ( item. value, codingPath: codingPath)
140-
141135 let keyedContainer = TLVKeyedDecodingContainer < Key > ( referencing: self , wrapping: items)
142-
143136 return KeyedDecodingContainer ( keyedContainer)
144137 }
145138 }
@@ -159,16 +152,15 @@ internal extension TLVDecoder {
159152 case let . item( item) :
160153
161154 // forceably cast to array
162- guard let items = try ? TLVDecoder . decode ( item. value, codingPath: codingPath) else {
163-
164- throw DecodingError . typeMismatch ( UnkeyedDecodingContainer . self, DecodingError . Context ( codingPath: self . codingPath, debugDescription: " Cannot get unkeyed decoding container, invalid top container \( container) . " ) )
155+ do {
156+ let items = try TLVDecoder . decode ( item. value, codingPath: codingPath)
157+ self . stack. pop ( ) // replace stack
158+ self . stack. push ( . items( items) )
159+ return TLVUnkeyedDecodingContainer ( referencing: self , wrapping: items)
160+ } catch {
161+ log ? ( " Could not decode for unkeyed container: \( error) " )
162+ throw DecodingError . dataCorrupted ( DecodingError . Context ( codingPath: self . codingPath, debugDescription: " Cannot get unkeyed decoding container, invalid top container \( container) . " ) )
165163 }
166-
167- // replace stack
168- self . stack. pop ( )
169- self . stack. push ( . items( items) )
170-
171- return TLVUnkeyedDecodingContainer ( referencing: self , wrapping: items)
172164 }
173165 }
174166
@@ -196,6 +188,37 @@ internal extension TLVDecoder.Decoder {
196188 }
197189}
198190
191+ // MARK: - Coding Key
192+
193+ internal extension TLVDecoder . Decoder {
194+
195+ func typeCode < Key: CodingKey > ( for key: Key ) throws -> TLVTypeCode {
196+
197+ if let tlvCodingKey = key as? TLVCodingKey {
198+
199+ return tlvCodingKey. code
200+
201+ } else if let intValue = key. intValue {
202+
203+ guard intValue <= Int ( UInt8 . max) ,
204+ intValue >= Int ( UInt8 . min) else {
205+ throw DecodingError . keyNotFound ( key, DecodingError . Context ( codingPath: codingPath, debugDescription: " Coding key \( key) has an invalid integer value \( intValue) " ) )
206+ }
207+
208+ return TLVTypeCode ( rawValue: UInt8 ( intValue) )
209+
210+ } else if MemoryLayout< Key> . size == MemoryLayout< UInt8> . size,
211+ Mirror ( reflecting: key) . displayStyle == . enum {
212+
213+ return TLVTypeCode ( rawValue: unsafeBitCast ( key, to: UInt8 . self) )
214+
215+ } else {
216+
217+ throw DecodingError . keyNotFound ( key, DecodingError . Context ( codingPath: codingPath, debugDescription: " Coding key \( key) has no integer value " ) )
218+ }
219+ }
220+ }
221+
199222// MARK: - Unboxing Values
200223
201224internal extension TLVDecoder . Decoder {
@@ -210,21 +233,29 @@ internal extension TLVDecoder.Decoder {
210233 return value
211234 }
212235
236+ func unboxNumeric < T: TLVDecodable & FixedWidthInteger > ( _ data: Data , as type: T . Type ) throws -> T {
237+
238+ var numericValue = try unbox ( data, as: type)
239+ switch options. numericFormat {
240+ case . bigEndian:
241+ numericValue = T . init ( bigEndian: numericValue)
242+ case . littleEndian:
243+ numericValue = T . init ( littleEndian: numericValue)
244+ }
245+ return numericValue
246+ }
247+
213248 /// Attempt to decode native value to expected type.
214249 func unboxDecodable < T: Decodable > ( _ item: TLVItem , as type: T . Type ) throws -> T {
215250
216251 // override for native types
217252 if type == Data . self {
218-
219253 return item. value as! T // In this case T is Data
220-
221254 } else {
222-
223255 // push container to stack and decode using Decodable implementation
224256 stack. push ( . item( item) )
225257 let decoded = try T ( from: self )
226258 stack. pop ( )
227-
228259 return decoded
229260 }
230261 }
@@ -279,28 +310,28 @@ fileprivate extension TLVDecoder.Stack {
279310
280311// MARK: - KeyedDecodingContainer
281312
282- internal struct TLVKeyedDecodingContainer < K : CodingKey > : KeyedDecodingContainerProtocol {
313+ internal struct TLVKeyedDecodingContainer < K: CodingKey > : KeyedDecodingContainerProtocol {
283314
284315 typealias Key = K
285316
286317 // MARK: Properties
287318
288319 /// A reference to the encoder we're reading from.
289- private let decoder : TLVDecoder . Decoder
320+ let decoder : TLVDecoder . Decoder
290321
291322 /// A reference to the container we're reading from.
292- private let container : [ TLVItem ]
323+ let container : [ TLVItem ]
293324
294325 /// The path of coding keys taken to get to this point in decoding.
295- public let codingPath : [ CodingKey ]
326+ let codingPath : [ CodingKey ]
296327
297328 /// All the keys the Decoder has for this container.
298- public let allKeys : [ Key ]
329+ let allKeys : [ Key ]
299330
300331 // MARK: Initialization
301332
302333 /// Initializes `self` by referencing the given decoder and container.
303- fileprivate init ( referencing decoder: TLVDecoder . Decoder , wrapping container: [ TLVItem ] ) {
334+ init ( referencing decoder: TLVDecoder . Decoder , wrapping container: [ TLVItem ] ) {
304335
305336 self . decoder = decoder
306337 self . container = container
@@ -312,18 +343,9 @@ internal struct TLVKeyedDecodingContainer <K : CodingKey >: KeyedDecodingContain
312343
313344 func contains( _ key: Key ) -> Bool {
314345
315- // log
316346 self . decoder. log ? ( " Check whether key \" \( key. stringValue) \" exists " )
317-
318- // check schema / model contains property
319- // FIXME: Remove unneccesary check as optimization
320- guard allKeys. contains ( where: { $0. stringValue == key. stringValue } )
347+ guard let typeCode = try ? self . decoder. typeCode ( for: key)
321348 else { return false }
322-
323- // return whether value exists for key
324- guard let typeCode = TLVTypeCode ( codingKey: key)
325- else { return false }
326-
327349 return container. contains { $0. type == typeCode }
328350 }
329351
@@ -338,93 +360,81 @@ internal struct TLVKeyedDecodingContainer <K : CodingKey >: KeyedDecodingContain
338360
339361 func decode( _ type: Bool . Type , forKey key: Key ) throws -> Bool {
340362
341- return try _decode ( type, forKey: key)
363+ return try decodeTLV ( type, forKey: key)
342364 }
343365
344366 func decode( _ type: Int . Type , forKey key: Key ) throws -> Int {
345367
346- let value = try _decode ( Int32 . self, forKey: key)
347-
368+ let value = try decodeNumeric ( Int32 . self, forKey: key)
348369 return Int ( value)
349370 }
350371
351372 func decode( _ type: Int8 . Type , forKey key: Key ) throws -> Int8 {
352373
353- return try _decode ( type, forKey: key)
374+ return try decodeTLV ( type, forKey: key)
354375 }
355376
356377 func decode( _ type: Int16 . Type , forKey key: Key ) throws -> Int16 {
357378
358- return try _decode ( type, forKey: key)
379+ return try decodeNumeric ( type, forKey: key)
359380 }
360381
361382 func decode( _ type: Int32 . Type , forKey key: Key ) throws -> Int32 {
362383
363- return try _decode ( type, forKey: key)
384+ return try decodeNumeric ( type, forKey: key)
364385 }
365386
366387 func decode( _ type: Int64 . Type , forKey key: Key ) throws -> Int64 {
367388
368- return try _decode ( type, forKey: key)
389+ return try decodeNumeric ( type, forKey: key)
369390 }
370391
371392 func decode( _ type: UInt . Type , forKey key: Key ) throws -> UInt {
372393
373- let value = try _decode ( UInt32 . self, forKey: key)
374-
394+ let value = try decodeNumeric ( UInt32 . self, forKey: key)
375395 return UInt ( value)
376396 }
377397
378398 func decode( _ type: UInt8 . Type , forKey key: Key ) throws -> UInt8 {
379399
380- return try _decode ( type, forKey: key)
400+ return try decodeTLV ( type, forKey: key)
381401 }
382402
383403 func decode( _ type: UInt16 . Type , forKey key: Key ) throws -> UInt16 {
384404
385- return try _decode ( type, forKey: key)
405+ return try decodeNumeric ( type, forKey: key)
386406 }
387407
388408 func decode( _ type: UInt32 . Type , forKey key: Key ) throws -> UInt32 {
389409
390- return try _decode ( type, forKey: key)
410+ return try decodeNumeric ( type, forKey: key)
391411 }
392412
393413 func decode( _ type: UInt64 . Type , forKey key: Key ) throws -> UInt64 {
394414
395- return try _decode ( type, forKey: key)
415+ return try decodeNumeric ( type, forKey: key)
396416 }
397417
398418 func decode( _ type: Float . Type , forKey key: Key ) throws -> Float {
399419
400- let bitPattern = try _decode ( UInt32 . self, forKey: key)
420+ let bitPattern = try decodeNumeric ( UInt32 . self, forKey: key)
401421 return Float ( bitPattern: bitPattern)
402422 }
403423
404424 func decode( _ type: Double . Type , forKey key: Key ) throws -> Double {
405425
406- let bitPattern = try _decode ( UInt64 . self, forKey: key)
426+ let bitPattern = try decodeNumeric ( UInt64 . self, forKey: key)
407427 return Double ( bitPattern: bitPattern)
408428 }
409429
410430 func decode( _ type: String . Type , forKey key: Key ) throws -> String {
411431
412- return try _decode ( type, forKey: key)
432+ return try decodeTLV ( type, forKey: key)
413433 }
414434
415435 func decode < T: Decodable > ( _ type: T . Type , forKey key: Key ) throws -> T {
416436
417- self . decoder. codingPath. append ( key)
418- defer { self . decoder. codingPath. removeLast ( ) }
419-
420- guard let item = try self . value ( for: key) else {
421-
422- throw DecodingError . valueNotFound ( type, DecodingError . Context ( codingPath: self . decoder. codingPath, debugDescription: " Expected \( type) value but found null instead. " ) )
423- }
424-
425- let value = try self . decoder. unboxDecodable ( item, as: type)
426-
427- return value
437+ return try self . value ( for: key, type: type) { try decoder. unboxDecodable ( $0, as: type) }
428438 }
429439
430440 func nestedContainer< NestedKey> ( keyedBy type: NestedKey . Type , forKey key: Key ) throws -> KeyedDecodingContainer < NestedKey > where NestedKey : CodingKey {
@@ -450,29 +460,34 @@ internal struct TLVKeyedDecodingContainer <K : CodingKey >: KeyedDecodingContain
450460 // MARK: Private Methods
451461
452462 /// Decode native value type from TLV data.
453- private func _decode < T: TLVDecodable > ( _ type: T . Type , forKey key: Key ) throws -> T {
463+ private func decodeTLV < T: TLVDecodable > ( _ type: T . Type , forKey key: Key ) throws -> T {
464+
465+ return try self . value ( for: key, type: type) { try decoder. unbox ( $0. value, as: type) }
466+ }
467+
468+ private func decodeNumeric < T: TLVDecodable & FixedWidthInteger > ( _ type: T . Type , forKey key: Key ) throws -> T {
469+
470+ return try self . value ( for: key, type: type) { try decoder. unboxNumeric ( $0. value, as: type) }
471+ }
472+
473+ /// Access actual value
474+ @inline ( __always)
475+ private func value < T> ( for key: Key , type: T . Type , decode: ( TLVItem ) throws -> T ) throws -> T {
454476
455477 self . decoder. codingPath. append ( key)
456478 defer { self . decoder. codingPath. removeLast ( ) }
457-
458479 guard let item = try self . value ( for: key) else {
459-
460480 throw DecodingError . valueNotFound ( type, DecodingError . Context ( codingPath: self . decoder. codingPath, debugDescription: " Expected \( type) value but found null instead. " ) )
461481 }
462-
463- let data = item. value
464- let value = try decoder. unbox ( data, as: type)
465- return value
482+ return try decode ( item)
466483 }
467484
468485 /// Access actual value
469486 private func value( for key: Key ) throws -> TLVItem ? {
470487
471- // log
472- decoder. log ? ( " Will read value for key \( key. stringValue) at path \" \( decoder. codingPath. path) \" " )
473-
474- // get value
475- return container. first { $0. type == TLVTypeCode ( codingKey: key) }
488+ decoder. log ? ( " Will read value at path \" \( decoder. codingPath. path) \" " )
489+ let typeCode = try self . decoder. typeCode ( for: key)
490+ return container. first { $0. type == typeCode }
476491 }
477492}
478493
@@ -718,19 +733,17 @@ internal struct TLVUnkeyedDecodingContainer: UnkeyedDecodingContainer {
718733 }
719734}
720735
721- fileprivate extension TLVUnkeyedDecodingContainer {
736+ internal extension TLVUnkeyedDecodingContainer {
722737
723738 struct Index : CodingKey {
724739
725740 public let index : Int
726741
727742 public init ( intValue: Int ) {
728-
729743 self . index = intValue
730744 }
731745
732- init ? ( stringValue: String ) {
733-
746+ public init ? ( stringValue: String ) {
734747 return nil
735748 }
736749
0 commit comments