@@ -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
227231internal 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