@@ -213,7 +213,7 @@ extension StructuredFieldValueParser {
213213
214214 switch first {
215215 case asciiDash, asciiDigits:
216- return try self . _parseAnIntegerOrDecimal ( )
216+ return try self . _parseAnIntegerOrDecimal ( isDate : false )
217217 case asciiDquote:
218218 return try self . _parseAString ( )
219219 case asciiColon:
@@ -222,12 +222,14 @@ extension StructuredFieldValueParser {
222222 return try self . _parseABoolean ( )
223223 case asciiCapitals, asciiLowercases, asciiAsterisk:
224224 return try self . _parseAToken ( )
225+ case asciiAt:
226+ return try self . _parseADate ( )
225227 default :
226228 throw StructuredHeaderError . invalidItem
227229 }
228230 }
229231
230- private mutating func _parseAnIntegerOrDecimal( ) throws -> RFC9651BareItem {
232+ private mutating func _parseAnIntegerOrDecimal( isDate : Bool ) throws -> RFC9651BareItem {
231233 var sign = 1
232234 var type = IntegerOrDecimal . integer
233235
@@ -248,10 +250,19 @@ extension StructuredFieldValueParser {
248250 // Do nothing
249251 ( )
250252 case asciiPeriod where type == . in teger:
253+ // If output_date is decimal, fail parsing.
254+ if isDate {
255+ throw StructuredHeaderError . invalidDate
256+ }
257+
251258 // If input_number contains more than 12 characters, fail parsing. Otherwise,
252259 // set type to decimal and consume.
253260 if self . underlyingData. distance ( from: self . underlyingData. startIndex, to: index) > 12 {
254- throw StructuredHeaderError . invalidIntegerOrDecimal
261+ if isDate {
262+ throw StructuredHeaderError . invalidDate
263+ } else {
264+ throw StructuredHeaderError . invalidIntegerOrDecimal
265+ }
255266 }
256267 type = . decimal
257268 default:
@@ -268,9 +279,15 @@ extension StructuredFieldValueParser {
268279 switch type {
269280 case . integer:
270281 if count > 15 {
271- throw StructuredHeaderError . invalidIntegerOrDecimal
282+ if isDate {
283+ throw StructuredHeaderError . invalidDate
284+ } else {
285+ throw StructuredHeaderError . invalidIntegerOrDecimal
286+ }
272287 }
273288 case . decimal:
289+ assert ( isDate == false )
290+
274291 if count > 16 {
275292 throw StructuredHeaderError . invalidIntegerOrDecimal
276293 }
@@ -286,7 +303,13 @@ extension StructuredFieldValueParser {
286303 // This intermediate string is sad, we should rewrite this manually to avoid it.
287304 // This force-unwrap is safe, as we have validated that all characters are ascii digits.
288305 let baseInt = Int ( String ( decoding: integerBytes, as: UTF8 . self) , radix: 10 ) !
289- return . integer( baseInt * sign)
306+ let resultingInt = baseInt * sign
307+
308+ if isDate {
309+ return . date( resultingInt)
310+ } else {
311+ return . integer( resultingInt)
312+ }
290313 case . decimal:
291314 // This must be non-nil, otherwise we couldn't have flipped to the decimal type.
292315 let periodIndex = integerBytes. firstIndex ( of: asciiPeriod) !
@@ -459,6 +482,12 @@ extension StructuredFieldValueParser {
459482 return . token( String ( decoding: tokenSlice, as: UTF8 . self) )
460483 }
461484
485+ private mutating func _parseADate( ) throws -> RFC9651 BareItem {
486+ assert ( self . underlyingData. first == asciiAt)
487+ self . underlyingData. consumeFirst ( )
488+ return try self . _parseAnIntegerOrDecimal ( isDate: true )
489+ }
490+
462491 private mutating func _parseParameters( ) throws -> OrderedMap< Key, RFC9651 BareItem> {
463492 var parameters = OrderedMap < Key , RFC9651BareItem > ( )
464493
0 commit comments