Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 68530a4

Browse files
authored
Merge pull request #5 from PureSwift/feature/date
Implemented Date decoding
2 parents 8c41d0f + b9960b8 commit 68530a4

File tree

5 files changed

+276
-45
lines changed

5 files changed

+276
-45
lines changed

Sources/Decoder.swift

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public struct TLVDecoder {
2525
/// Format for UUID values.
2626
public var uuidFormat: TLVUUIDFormat = .bytes
2727

28+
/// Format for Date values.
29+
public var dateFormat: TLVDateFormat = .secondsSince1970
30+
2831
// MARK: - Initialization
2932

3033
public init() { }
@@ -39,7 +42,8 @@ public struct TLVDecoder {
3942

4043
let options = Decoder.Options(
4144
numericFormat: numericFormat,
42-
uuidFormat: uuidFormat
45+
uuidFormat: uuidFormat,
46+
dateFormat: dateFormat
4347
)
4448

4549
let decoder = Decoder(referencing: .items(items),
@@ -226,7 +230,7 @@ internal extension TLVDecoder.Decoder {
226230

227231
internal extension TLVDecoder.Decoder {
228232

229-
func unbox <T: TLVDecodable> (_ data: Data, as type: T.Type) throws -> T {
233+
func unbox <T: TLVRawDecodable> (_ data: Data, as type: T.Type) throws -> T {
230234

231235
guard let value = T.init(tlvData: data) else {
232236

@@ -236,7 +240,7 @@ internal extension TLVDecoder.Decoder {
236240
return value
237241
}
238242

239-
func unboxNumeric <T: TLVDecodable & FixedWidthInteger> (_ data: Data, as type: T.Type) throws -> T {
243+
func unboxNumeric <T: TLVRawDecodable & FixedWidthInteger> (_ data: Data, as type: T.Type) throws -> T {
240244

241245
var numericValue = try unbox(data, as: type)
242246
switch options.numericFormat {
@@ -248,6 +252,16 @@ internal extension TLVDecoder.Decoder {
248252
return numericValue
249253
}
250254

255+
func unboxDouble(_ data: Data) throws -> Double {
256+
let bitPattern = try unboxNumeric(data, as: UInt64.self)
257+
return Double(bitPattern: bitPattern)
258+
}
259+
260+
func unboxFloat(_ data: Data) throws -> Float {
261+
let bitPattern = try unboxNumeric(data, as: UInt32.self)
262+
return Float(bitPattern: bitPattern)
263+
}
264+
251265
/// Attempt to decode native value to expected type.
252266
func unboxDecodable <T: Decodable> (_ item: TLVItem, as type: T.Type) throws -> T {
253267

@@ -256,6 +270,8 @@ internal extension TLVDecoder.Decoder {
256270
return item.value as! T // In this case T is Data
257271
} else if type == UUID.self {
258272
return try unboxUUID(item.value) as! T
273+
} else if type == Date.self {
274+
return try unboxDate(item.value) as! T
259275
} else if let tlvCodable = type as? TLVCodable.Type {
260276
guard let value = tlvCodable.init(tlvData: item.value) else {
261277
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Invalid data for \(String(reflecting: type))"))
@@ -269,8 +285,11 @@ internal extension TLVDecoder.Decoder {
269285
return decoded
270286
}
271287
}
288+
}
289+
290+
private extension TLVDecoder.Decoder {
272291

273-
private func unboxUUID(_ data: Data) throws -> UUID {
292+
func unboxUUID(_ data: Data) throws -> UUID {
274293

275294
switch options.uuidFormat {
276295
case .bytes:
@@ -288,6 +307,33 @@ internal extension TLVDecoder.Decoder {
288307
return uuid
289308
}
290309
}
310+
311+
func unboxDate(_ data: Data) throws -> Date {
312+
313+
switch options.dateFormat {
314+
case .secondsSince1970:
315+
let timeInterval = try unboxDouble(data)
316+
return Date(timeIntervalSince1970: timeInterval)
317+
case .millisecondsSince1970:
318+
let timeInterval = try unboxDouble(data)
319+
return Date(timeIntervalSince1970: timeInterval / 1000)
320+
case .iso8601:
321+
guard #available(OSX 10.12, *)
322+
else { fatalError("ISO8601DateFormatter is unavailable on this platform.") }
323+
return try unboxDate(data, using: TLVDateFormat.iso8601Formatter)
324+
case let .formatted(formatter):
325+
return try unboxDate(data, using: formatter)
326+
}
327+
}
328+
329+
@inline(__always)
330+
func unboxDate <T: DateFormatterProtocol> (_ data: Data, using formatter: T) throws -> Date {
331+
let string = try unbox(data, as: String.self)
332+
guard let date = formatter.date(from: string) else {
333+
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Invalid Date string \(string)"))
334+
}
335+
return date
336+
}
291337
}
292338

293339
// MARK: - Stack
@@ -489,12 +535,12 @@ internal struct TLVKeyedDecodingContainer <K: CodingKey> : KeyedDecodingContaine
489535
// MARK: Private Methods
490536

491537
/// Decode native value type from TLV data.
492-
private func decodeTLV <T: TLVDecodable> (_ type: T.Type, forKey key: Key) throws -> T {
538+
private func decodeTLV <T: TLVRawDecodable> (_ type: T.Type, forKey key: Key) throws -> T {
493539

494540
return try self.value(for: key, type: type) { try decoder.unbox($0.value, as: type) }
495541
}
496542

497-
private func decodeNumeric <T: TLVDecodable & FixedWidthInteger> (_ type: T.Type, forKey key: Key) throws -> T {
543+
private func decodeNumeric <T: TLVRawDecodable & FixedWidthInteger> (_ type: T.Type, forKey key: Key) throws -> T {
498544

499545
return try self.value(for: key, type: type) { try decoder.unboxNumeric($0.value, as: type) }
500546
}
@@ -788,15 +834,21 @@ internal extension TLVUnkeyedDecodingContainer {
788834

789835
// MARK: - Decodable Types
790836

791-
extension String: TLVDecodable {
837+
/// Private protocol for decoding TLV values into raw data.
838+
internal protocol TLVRawDecodable {
839+
840+
init?(tlvData data: Data)
841+
}
842+
843+
extension String: TLVRawDecodable {
792844

793845
public init?(tlvData data: Data) {
794846

795847
self.init(data: data, encoding: .utf8)
796848
}
797849
}
798850

799-
extension Bool: TLVDecodable {
851+
extension Bool: TLVRawDecodable {
800852

801853
public init?(tlvData data: Data) {
802854

@@ -807,7 +859,7 @@ extension Bool: TLVDecodable {
807859
}
808860
}
809861

810-
extension UInt8: TLVDecodable {
862+
extension UInt8: TLVRawDecodable {
811863

812864
public init?(tlvData data: Data) {
813865

@@ -818,7 +870,7 @@ extension UInt8: TLVDecodable {
818870
}
819871
}
820872

821-
extension UInt16: TLVDecodable {
873+
extension UInt16: TLVRawDecodable {
822874

823875
public init?(tlvData data: Data) {
824876

@@ -829,7 +881,7 @@ extension UInt16: TLVDecodable {
829881
}
830882
}
831883

832-
extension UInt32: TLVDecodable {
884+
extension UInt32: TLVRawDecodable {
833885

834886
public init?(tlvData data: Data) {
835887

@@ -840,7 +892,7 @@ extension UInt32: TLVDecodable {
840892
}
841893
}
842894

843-
extension UInt64: TLVDecodable {
895+
extension UInt64: TLVRawDecodable {
844896

845897
public init?(tlvData data: Data) {
846898

@@ -851,7 +903,7 @@ extension UInt64: TLVDecodable {
851903
}
852904
}
853905

854-
extension Int8: TLVDecodable {
906+
extension Int8: TLVRawDecodable {
855907

856908
public init?(tlvData data: Data) {
857909

@@ -862,7 +914,7 @@ extension Int8: TLVDecodable {
862914
}
863915
}
864916

865-
extension Int16: TLVDecodable {
917+
extension Int16: TLVRawDecodable {
866918

867919
public init?(tlvData data: Data) {
868920

@@ -873,7 +925,7 @@ extension Int16: TLVDecodable {
873925
}
874926
}
875927

876-
extension Int32: TLVDecodable {
928+
extension Int32: TLVRawDecodable {
877929

878930
public init?(tlvData data: Data) {
879931

@@ -884,7 +936,7 @@ extension Int32: TLVDecodable {
884936
}
885937
}
886938

887-
extension Int64: TLVDecodable {
939+
extension Int64: TLVRawDecodable {
888940

889941
public init?(tlvData data: Data) {
890942

0 commit comments

Comments
 (0)