Skip to content

Commit c7b845d

Browse files
authored
Merge branch 'main' into align-semantic-version-check
2 parents 2b47403 + 6e527aa commit c7b845d

12 files changed

+222
-0
lines changed

Sources/StructuredFieldValues/Decoder/BareInnerListDecoder.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ extension BareInnerListDecoder: UnkeyedDecodingContainer {
7272
} else if type is Decimal.Type {
7373
let container = try self.decoder.singleValueContainer()
7474
return try container.decode(Decimal.self) as! T
75+
} else if type is Date.Type {
76+
let container = try self.decoder.singleValueContainer()
77+
return try container.decode(Date.self) as! T
7578
} else {
7679
return try type.init(from: self.decoder)
7780
}

Sources/StructuredFieldValues/Decoder/BareItemDecoder.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ extension BareItemDecoder: SingleValueDecodingContainer {
133133
)
134134
}
135135

136+
func decode(_: Date.Type) throws -> Date {
137+
guard case .date(let date) = self.item else {
138+
throw StructuredHeaderError.invalidTypeForItem
139+
}
140+
141+
return Date(timeIntervalSince1970: Double(date))
142+
}
143+
136144
func decodeNil() -> Bool {
137145
// Items are never nil.
138146
false
@@ -172,6 +180,8 @@ extension BareItemDecoder: SingleValueDecodingContainer {
172180
return try self.decode(Data.self) as! T
173181
case is Decimal.Type:
174182
return try self.decode(Decimal.self) as! T
183+
case is Date.Type:
184+
return try self.decode(Date.self) as! T
175185
default:
176186
throw StructuredHeaderError.invalidTypeForItem
177187
}

Sources/StructuredFieldValues/Decoder/DictionaryKeyedContainer.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ extension DictionaryKeyedContainer: KeyedDecodingContainerProtocol {
5555
} else if type is Decimal.Type {
5656
let container = try self.decoder.singleValueContainer()
5757
return try container.decode(Decimal.self) as! T
58+
} else if type is Date.Type {
59+
let container = try self.decoder.singleValueContainer()
60+
return try container.decode(Date.self) as! T
5861
} else {
5962
return try type.init(from: self.decoder)
6063
}

Sources/StructuredFieldValues/Decoder/KeyedInnerListDecoder.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ extension KeyedInnerListDecoder: KeyedDecodingContainerProtocol {
6060
} else if type is Decimal.Type {
6161
let container = try self.decoder.singleValueContainer()
6262
return try container.decode(Decimal.self) as! T
63+
} else if type is Date.Type {
64+
let container = try self.decoder.singleValueContainer()
65+
return try container.decode(Date.self) as! T
6366
} else {
6467
return try type.init(from: self.decoder)
6568
}

Sources/StructuredFieldValues/Decoder/KeyedItemDecoder.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ extension KeyedItemDecoder: KeyedDecodingContainerProtocol {
6060
} else if type is Decimal.Type {
6161
let container = try self.decoder.singleValueContainer()
6262
return try container.decode(Decimal.self) as! T
63+
} else if type is Date.Type {
64+
let container = try self.decoder.singleValueContainer()
65+
return try container.decode(Date.self) as! T
6366
} else {
6467
return try type.init(from: self.decoder)
6568
}

Sources/StructuredFieldValues/Decoder/KeyedTopLevelListDecoder.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ extension KeyedTopLevelListDecoder: KeyedDecodingContainerProtocol {
6060
} else if type is Decimal.Type {
6161
let container = try self.decoder.singleValueContainer()
6262
return try container.decode(Decimal.self) as! T
63+
} else if type is Date.Type {
64+
let container = try self.decoder.singleValueContainer()
65+
return try container.decode(Date.self) as! T
6366
} else {
6467
return try type.init(from: self.decoder)
6568
}

Sources/StructuredFieldValues/Decoder/ParametersDecoder.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ extension ParametersDecoder: KeyedDecodingContainerProtocol {
5555
} else if type is Decimal.Type {
5656
let container = try self.decoder.singleValueContainer()
5757
return try container.decode(Decimal.self) as! T
58+
} else if type is Date.Type {
59+
let container = try self.decoder.singleValueContainer()
60+
return try container.decode(Date.self) as! T
5861
} else {
5962
return try type.init(from: self.decoder)
6063
}

Sources/StructuredFieldValues/Decoder/StructuredFieldValueDecoder.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ extension StructuredFieldValueDecoder {
117117
} else if type is Decimal.Type {
118118
let container = try decoder.singleValueContainer()
119119
return try container.decode(Decimal.self) as! StructuredField
120+
} else if type is Date.Type {
121+
let container = try decoder.singleValueContainer()
122+
return try container.decode(Date.self) as! StructuredField
120123
} else {
121124
return try type.init(from: decoder)
122125
}

Sources/StructuredFieldValues/Decoder/TopLevelListDecoder.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ extension TopLevelListDecoder: UnkeyedDecodingContainer {
7272
} else if type is Decimal.Type {
7373
let container = try self.decoder.singleValueContainer()
7474
return try container.decode(Decimal.self) as! T
75+
} else if type is Date.Type {
76+
let container = try self.decoder.singleValueContainer()
77+
return try container.decode(Date.self) as! T
7578
} else {
7679
return try type.init(from: self.decoder)
7780
}

Sources/StructuredFieldValues/Encoder/StructuredFieldValueEncoder.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ class _StructuredFieldEncoder {
160160
try self.encode(value)
161161
} else if let value = data as? Decimal {
162162
try self.encode(value)
163+
} else if let value = data as? Date {
164+
try self.encode(value)
163165
} else {
164166
try data.encode(to: self)
165167
}
@@ -309,6 +311,11 @@ extension _StructuredFieldEncoder: SingleValueEncodingContainer {
309311
try self.currentStackEntry.storage.insertBareItem(.decimal(pd))
310312
}
311313

314+
func encode(_ data: Date) throws {
315+
let date = Int(data.timeIntervalSince1970)
316+
try self.currentStackEntry.storage.insertBareItem(.date(date))
317+
}
318+
312319
func encode<T>(_ value: T) throws where T: Encodable {
313320
switch value {
314321
case let value as UInt8:
@@ -343,6 +350,8 @@ extension _StructuredFieldEncoder: SingleValueEncodingContainer {
343350
try self.encode(value)
344351
case let value as Decimal:
345352
try self.encode(value)
353+
case let value as Date:
354+
try self.encode(value)
346355
default:
347356
throw StructuredHeaderError.invalidTypeForItem
348357
}
@@ -466,6 +475,11 @@ extension _StructuredFieldEncoder {
466475
try self.currentStackEntry.storage.appendBareItem(.decimal(pd))
467476
}
468477

478+
func append(_ value: Date) throws {
479+
let date = Int(value.timeIntervalSince1970)
480+
try self.currentStackEntry.storage.appendBareItem(.date(date))
481+
}
482+
469483
func append<T>(_ value: T) throws where T: Encodable {
470484
switch value {
471485
case let value as UInt8:
@@ -500,6 +514,8 @@ extension _StructuredFieldEncoder {
500514
try self.append(value)
501515
case let value as Decimal:
502516
try self.append(value)
517+
case let value as Date:
518+
try self.append(value)
503519
default:
504520
// Some other codable type.
505521
switch self.currentStackEntry.storage {
@@ -636,6 +652,12 @@ extension _StructuredFieldEncoder {
636652
try self.currentStackEntry.storage.insertBareItem(.decimal(pd), atKey: key)
637653
}
638654

655+
func encode(_ value: Date, forKey key: String) throws {
656+
let key = self.sanitizeKey(key)
657+
let date = Int(value.timeIntervalSince1970)
658+
try self.currentStackEntry.storage.insertBareItem(.date(date), atKey: key)
659+
}
660+
639661
func encode<T>(_ value: T, forKey key: String) throws where T: Encodable {
640662
let key = self.sanitizeKey(key)
641663

@@ -672,6 +694,8 @@ extension _StructuredFieldEncoder {
672694
try self.encode(value, forKey: key)
673695
case let value as Decimal:
674696
try self.encode(value, forKey: key)
697+
case let value as Date:
698+
try self.encode(value, forKey: key)
675699
default:
676700
// Ok, we don't know what this is. This can only happen for a dictionary, or
677701
// for anything with parameters, or for lists, or for inner lists.

Tests/StructuredFieldValuesTests/StructuredFieldDecoderTests.swift

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,4 +490,125 @@ final class StructuredFieldDecoderTests: XCTestCase {
490490
try StructuredFieldValueDecoder().decode(DictionaryField.self, from: Array(headerField.utf8))
491491
)
492492
}
493+
494+
func testDecodingDateAsTopLevelData() throws {
495+
let headerField = "@4294967296"
496+
XCTAssertEqual(
497+
ItemField(Date(timeIntervalSince1970: 4_294_967_296)),
498+
try StructuredFieldValueDecoder().decode(from: Array(headerField.utf8))
499+
)
500+
}
501+
502+
func testDecodingDateAsParameterisedData() throws {
503+
struct Item: StructuredFieldValue, Equatable {
504+
static let structuredFieldType: StructuredFieldType = .item
505+
var item: Date
506+
var parameters: [String: Float]
507+
}
508+
509+
let headerFieldNoParameters = "@4294967296"
510+
let headerFieldParameters = "@4294967296;q=0.8"
511+
512+
XCTAssertEqual(
513+
Item(
514+
item: Date(timeIntervalSince1970: 4_294_967_296),
515+
parameters: [:]
516+
),
517+
try StructuredFieldValueDecoder().decode(
518+
Item.self,
519+
from: Array(headerFieldNoParameters.utf8)
520+
)
521+
)
522+
523+
XCTAssertEqual(
524+
Item(item: Date(timeIntervalSince1970: 4_294_967_296), parameters: ["q": 0.8]),
525+
try StructuredFieldValueDecoder().decode(
526+
Item.self,
527+
from: Array(headerFieldParameters.utf8)
528+
)
529+
)
530+
}
531+
532+
func testDecodingDateInParameterField() throws {
533+
struct Item: StructuredFieldValue, Equatable {
534+
static let structuredFieldType: StructuredFieldType = .item
535+
var item: Int
536+
var parameters: [String: Date]
537+
}
538+
539+
let headerField = "1;q=@4294967296"
540+
XCTAssertEqual(
541+
Item(item: 1, parameters: ["q": Date(timeIntervalSince1970: 4_294_967_296)]),
542+
try StructuredFieldValueDecoder().decode(Item.self, from: Array(headerField.utf8))
543+
)
544+
}
545+
546+
func testDecodingDateInOuterListRaw() throws {
547+
let headerField = "@4294967296, @-1659578233"
548+
XCTAssertEqual(
549+
List(
550+
[
551+
Date(timeIntervalSince1970: 4_294_967_296),
552+
Date(timeIntervalSince1970: -1_659_578_233),
553+
]
554+
),
555+
try StructuredFieldValueDecoder().decode(from: Array(headerField.utf8))
556+
)
557+
}
558+
559+
func testDecodingDateInInnerListRaw() throws {
560+
let headerField = "(@4294967296 @-1659578233), (@4294967296 @-1659578233)"
561+
XCTAssertEqual(
562+
List(
563+
Array(
564+
repeating: [
565+
Date(timeIntervalSince1970: 4_294_967_296),
566+
Date(timeIntervalSince1970: -1_659_578_233),
567+
],
568+
count: 2
569+
)
570+
),
571+
try StructuredFieldValueDecoder().decode(from: Array(headerField.utf8))
572+
)
573+
}
574+
575+
func testDecodingDateInInnerListKeyed() throws {
576+
struct ListField: Codable, Equatable {
577+
var items: [Date]
578+
var parameters: [String: Bool]
579+
}
580+
let headerField = "(@4294967296 @-1659578233);foo, (@4294967296 @-1659578233);foo"
581+
XCTAssertEqual(
582+
List(
583+
Array(
584+
repeating: ListField(
585+
items: [
586+
Date(timeIntervalSince1970: 4_294_967_296),
587+
Date(timeIntervalSince1970: -1_659_578_233),
588+
],
589+
parameters: ["foo": true]
590+
),
591+
count: 2
592+
)
593+
),
594+
try StructuredFieldValueDecoder().decode(from: Array(headerField.utf8))
595+
)
596+
}
597+
598+
func testDecodingDateInDictionaries() throws {
599+
struct DictionaryField: StructuredFieldValue, Equatable {
600+
static let structuredFieldType: StructuredFieldType = .dictionary
601+
var bin: Date
602+
var box: Date
603+
}
604+
605+
let headerField = "bin=@4294967296, box=@-1659578233"
606+
XCTAssertEqual(
607+
DictionaryField(
608+
bin: Date(timeIntervalSince1970: 4_294_967_296),
609+
box: Date(timeIntervalSince1970: -1_659_578_233)
610+
),
611+
try StructuredFieldValueDecoder().decode(from: Array(headerField.utf8))
612+
)
613+
}
493614
}

Tests/StructuredFieldValuesTests/StructuredFieldEncoderTests.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ final class StructuredFieldEncoderTests: XCTestCase {
4343

4444
// Binary Data
4545
XCTAssertEqual(Array(":AQIDBA==:".utf8), try encoder.encode(ItemField(Data([1, 2, 3, 4]))))
46+
47+
// Date
48+
XCTAssertEqual(
49+
Array("@4294967296".utf8),
50+
try encoder.encode(ItemField(Date(timeIntervalSince1970: 4_294_967_296)))
51+
)
52+
XCTAssertEqual(
53+
Array("@-1659578233".utf8),
54+
try encoder.encode(ItemField(Date(timeIntervalSince1970: -1_659_578_233)))
55+
)
4656
}
4757

4858
func testEncodeKeyedItemHeader() throws {
@@ -96,6 +106,26 @@ final class StructuredFieldEncoderTests: XCTestCase {
96106
Array(":AQIDBA==:".utf8),
97107
try encoder.encode(KeyedItem(item: Data([1, 2, 3, 4]), parameters: [:]))
98108
)
109+
110+
// Date
111+
XCTAssertEqual(
112+
Array("@4294967296;x".utf8),
113+
try encoder.encode(
114+
KeyedItem(
115+
item: Date(timeIntervalSince1970: 4_294_967_296),
116+
parameters: ["x": true]
117+
)
118+
)
119+
)
120+
XCTAssertEqual(
121+
Array("@-1659578233".utf8),
122+
try encoder.encode(
123+
KeyedItem(
124+
item: Date(timeIntervalSince1970: -1_659_578_233),
125+
parameters: [:]
126+
)
127+
)
128+
)
99129
}
100130

101131
func testEncodeKeyedItemHeaderWithParamsAsStruct() throws {
@@ -189,6 +219,19 @@ final class StructuredFieldEncoderTests: XCTestCase {
189219
Array(":AQIDBA==:, :BQYHCA==:".utf8),
190220
try encoder.encode(List([Data([1, 2, 3, 4]), Data([5, 6, 7, 8])]))
191221
)
222+
223+
// Date
224+
XCTAssertEqual(
225+
Array("@4294967296, @-1659578233".utf8),
226+
try encoder.encode(
227+
List(
228+
[
229+
Date(timeIntervalSince1970: 4_294_967_296),
230+
Date(timeIntervalSince1970: -1_659_578_233),
231+
]
232+
)
233+
)
234+
)
192235
}
193236

194237
func testListFieldInnerItemsWithDict() throws {

0 commit comments

Comments
 (0)