in Sources/StructuredFieldValues/Decoder/StructuredFieldValueDecoder.swift [231:302]
func innerElement(for key: _StructuredHeaderCodingKey) throws -> Element {
switch self {
case .dictionary(let dictionary):
guard let element = dictionary.first(where: { $0.0 == key.stringValue }) else {
throw StructuredHeaderError.invalidTypeForItem
}
switch element.1 {
case .item(let item):
return .item(item)
case .innerList(let innerList):
return .innerList(innerList)
}
case .list(let list):
if let offset = key.intValue {
guard offset < list.count else {
throw StructuredHeaderError.invalidTypeForItem
}
let index = list.index(list.startIndex, offsetBy: offset)
switch list[index] {
case .item(let item):
return .item(item)
case .innerList(let innerList):
return .innerList(innerList)
}
} else if key.stringValue == "items" {
// Oh, the outer layer is keyed. That's fine, just put ourselves
// back on the stack.
return .list(list)
} else {
throw StructuredHeaderError.invalidTypeForItem
}
case .item(let item):
// Two keys, "item" and "parameters".
switch key.stringValue {
case "item":
return .bareItem(item.bareItem)
case "parameters":
return .parameters(item.parameters)
default:
throw StructuredHeaderError.invalidTypeForItem
}
case .innerList(let innerList):
// Quick check: is this an integer key? If it is, treat this like a bare inner list. Otherwise
// there are two string keys: "items" and "parameters"
if key.intValue != nil {
return try Element.bareInnerList(innerList.bareInnerList).innerElement(for: key)
}
switch key.stringValue {
case "items":
return .bareInnerList(innerList.bareInnerList)
case "parameters":
return .parameters(innerList.parameters)
default:
throw StructuredHeaderError.invalidTypeForItem
}
case .bareItem:
// Bare items may never be parsed through.
throw StructuredHeaderError.invalidTypeForItem
case .bareInnerList(let innerList):
guard let offset = key.intValue, offset < innerList.count else {
throw StructuredHeaderError.invalidTypeForItem
}
let index = innerList.index(innerList.startIndex, offsetBy: offset)
return .item(innerList[index])
case .parameters(let params):
guard let element = params.first(where: { $0.0 == key.stringValue }) else {
throw StructuredHeaderError.invalidTypeForItem
}
return .bareItem(element.1)
}
}