Skip to content

Commit a894a26

Browse files
committed
Working on Decoder
1 parent ec2fb22 commit a894a26

1 file changed

Lines changed: 93 additions & 80 deletions

File tree

Sources/Decoder.swift

Lines changed: 93 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -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

201224
internal 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

Comments
 (0)