Skip to content

Commit 882cb88

Browse files
committed
Make dictionary/parameter keys strings too
1 parent f07f692 commit 882cb88

File tree

8 files changed

+42
-41
lines changed

8 files changed

+42
-41
lines changed

Sources/StructuredHeaders/ComponentTypes.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ extension BareItem: Hashable { }
6868
// MARK:- Item
6969
public struct Item<BaseData: RandomAccessCollection> where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
7070
public var bareItem: BareItem<BaseData>
71-
public var parameters: OrderedMap<BaseData, BareItem<BaseData>>
71+
public var parameters: OrderedMap<String, BareItem<BaseData>>
7272

73-
public init(bareItem: BareItem<BaseData>, parameters: OrderedMap<BaseData, BareItem<BaseData>>) {
73+
public init(bareItem: BareItem<BaseData>, parameters: OrderedMap<String, BareItem<BaseData>>) {
7474
self.bareItem = bareItem
7575
self.parameters = parameters
7676
}
@@ -152,9 +152,9 @@ extension BareInnerList.Index: Comparable {
152152
// MARK:- InnerList
153153
public struct InnerList<BaseData: RandomAccessCollection>: Hashable where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
154154
public var bareInnerList: BareInnerList<BaseData>
155-
public var parameters: OrderedMap<BaseData, BareItem<BaseData>>
155+
public var parameters: OrderedMap<String, BareItem<BaseData>>
156156

157-
public init(bareInnerList: BareInnerList<BaseData>, parameters: OrderedMap<BaseData, BareItem<BaseData>>) {
157+
public init(bareInnerList: BareInnerList<BaseData>, parameters: OrderedMap<String, BareItem<BaseData>>) {
158158
self.bareInnerList = bareInnerList
159159
self.parameters = parameters
160160
}

Sources/StructuredHeaders/Decoder/DictionaryKeyedContainer.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
struct DictionaryKeyedContainer<Key: CodingKey, BaseData: RandomAccessCollection> where BaseData.Element == UInt8, BaseData.SubSequence: Hashable {
16-
private var dictionary: OrderedMap<BaseData.SubSequence, ItemOrInnerList<BaseData.SubSequence>>
16+
private var dictionary: OrderedMap<String, ItemOrInnerList<BaseData.SubSequence>>
1717

1818
private var decoder: _StructuredFieldDecoder<BaseData>
1919

20-
init(_ dictionary: OrderedMap<BaseData.SubSequence, ItemOrInnerList<BaseData.SubSequence>>, decoder: _StructuredFieldDecoder<BaseData>) {
20+
init(_ dictionary: OrderedMap<String, ItemOrInnerList<BaseData.SubSequence>>, decoder: _StructuredFieldDecoder<BaseData>) {
2121
self.dictionary = dictionary
2222
self.decoder = decoder
2323
}
@@ -29,11 +29,11 @@ extension DictionaryKeyedContainer: KeyedDecodingContainerProtocol {
2929
}
3030

3131
var allKeys: [Key] {
32-
return self.dictionary.compactMap { Key(stringValue: String(decoding: $0.0, as: UTF8.self)) }
32+
return self.dictionary.compactMap { Key(stringValue: $0.0) }
3333
}
3434

3535
func contains(_ key: Key) -> Bool {
36-
return self.dictionary.contains(where: { $0.0.elementsEqual(key.stringValue.utf8) })
36+
return self.dictionary.contains(where: { $0.0 == key.stringValue })
3737
}
3838

3939
func decodeNil(forKey key: Key) throws -> Bool {

Sources/StructuredHeaders/Decoder/ParametersDecoder.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
struct ParametersDecoder<Key: CodingKey, BaseData: RandomAccessCollection> where BaseData.Element == UInt8, BaseData.SubSequence: Hashable {
16-
private var parameters: OrderedMap<BaseData.SubSequence, BareItem<BaseData.SubSequence>>
16+
private var parameters: OrderedMap<String, BareItem<BaseData.SubSequence>>
1717

1818
private var decoder: _StructuredFieldDecoder<BaseData>
1919

20-
init(_ parameters: OrderedMap<BaseData.SubSequence, BareItem<BaseData.SubSequence>>, decoder: _StructuredFieldDecoder<BaseData>) {
20+
init(_ parameters: OrderedMap<String, BareItem<BaseData.SubSequence>>, decoder: _StructuredFieldDecoder<BaseData>) {
2121
self.parameters = parameters
2222
self.decoder = decoder
2323
}
@@ -29,11 +29,11 @@ extension ParametersDecoder: KeyedDecodingContainerProtocol {
2929
}
3030

3131
var allKeys: [Key] {
32-
return self.parameters.compactMap { Key(stringValue: String(decoding: $0.0, as: UTF8.self)) }
32+
return self.parameters.compactMap { Key(stringValue: $0.0) }
3333
}
3434

3535
func contains(_ key: Key) -> Bool {
36-
return self.parameters.contains(where: { $0.0.elementsEqual(key.stringValue.utf8) })
36+
return self.parameters.contains(where: { $0.0 == key.stringValue })
3737
}
3838

3939
func decodeNil(forKey key: Key) throws -> Bool {

Sources/StructuredHeaders/Decoder/StructuredFieldDecoder.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,18 +185,18 @@ extension _StructuredFieldDecoder: Decoder {
185185
extension _StructuredFieldDecoder {
186186
/// The basic elements that make up a Structured Header
187187
fileprivate enum Element {
188-
case dictionary(OrderedMap<BaseData.SubSequence, ItemOrInnerList<BaseData.SubSequence>>)
188+
case dictionary(OrderedMap<String, ItemOrInnerList<BaseData.SubSequence>>)
189189
case list([ItemOrInnerList<BaseData.SubSequence>])
190190
case item(Item<BaseData.SubSequence>)
191191
case innerList(InnerList<BaseData.SubSequence>)
192192
case bareItem(BareItem<BaseData.SubSequence>)
193193
case bareInnerList(BareInnerList<BaseData.SubSequence>)
194-
case parameters(OrderedMap<BaseData.SubSequence, BareItem<BaseData.SubSequence>>)
194+
case parameters(OrderedMap<String, BareItem<BaseData.SubSequence>>)
195195

196196
func innerElement(for key: _StructuredHeaderCodingKey) throws -> Element {
197197
switch self {
198198
case .dictionary(let dictionary):
199-
guard let element = dictionary.first(where: { $0.0.elementsEqual(key.stringValue.utf8) }) else {
199+
guard let element = dictionary.first(where: { $0.0 == key.stringValue }) else {
200200
throw StructuredHeaderError.invalidTypeForItem
201201
}
202202
switch element.1 {
@@ -251,7 +251,7 @@ extension _StructuredFieldDecoder {
251251
let index = innerList.index(innerList.startIndex, offsetBy: offset)
252252
return .item(innerList[index])
253253
case .parameters(let params):
254-
guard let element = params.first(where: { $0.0.elementsEqual(key.stringValue.utf8) }) else {
254+
guard let element = params.first(where: { $0.0 == key.stringValue }) else {
255255
throw StructuredHeaderError.invalidTypeForItem
256256
}
257257
return .bareItem(element.1)

Sources/StructuredHeaders/FieldParser.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extension StructuredFieldParser {
3232
public typealias BareInnerList = StructuredHeaders.BareInnerList<BaseData.SubSequence>
3333
public typealias InnerList = StructuredHeaders.InnerList<BaseData.SubSequence>
3434
public typealias ItemOrInnerList = StructuredHeaders.ItemOrInnerList<BaseData.SubSequence>
35-
public typealias Key = BaseData.SubSequence
35+
public typealias Key = String
3636

3737
/// Parse the HTTP structured field as a list.
3838
///
@@ -446,8 +446,8 @@ extension StructuredFieldParser {
446446
return .token(String(decoding: tokenSlice, as: UTF8.self))
447447
}
448448

449-
private mutating func _parseParameters() throws -> OrderedMap<BaseData.SubSequence, BareItem> {
450-
var parameters = OrderedMap<BaseData.SubSequence, BareItem>()
449+
private mutating func _parseParameters() throws -> OrderedMap<Key, BareItem> {
450+
var parameters = OrderedMap<Key, BareItem>()
451451

452452
// We want to loop while we still have bytes _and_ while the first character is asciiSemicolon.
453453
// This covers both.
@@ -469,7 +469,7 @@ extension StructuredFieldParser {
469469
return parameters
470470
}
471471

472-
private mutating func _parseAKey() throws -> BaseData.SubSequence {
472+
private mutating func _parseAKey() throws -> Key {
473473
guard let first = self.underlyingData.first, asciiLowercases.contains(first) || first == asciiAsterisk else {
474474
throw StructuredHeaderError.invalidKey
475475
}
@@ -483,7 +483,7 @@ extension StructuredFieldParser {
483483
}
484484
})
485485
self.underlyingData = self.underlyingData.dropFirst(key.count)
486-
return key
486+
return String(decoding: key, as: UTF8.self)
487487
}
488488
}
489489

Sources/StructuredHeaders/FieldSerializer.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public struct StructuredFieldSerializer {
2727

2828
extension StructuredFieldSerializer {
2929
// TODO: decide if this is the best API, it forces allocations.
30-
public mutating func writeDictionaryHeader<BaseData: RandomAccessCollection>(_ root: OrderedMap<BaseData, ItemOrInnerList<BaseData>>) throws -> [UInt8] where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
30+
public mutating func writeDictionaryHeader<BaseData: RandomAccessCollection>(_ root: OrderedMap<String, ItemOrInnerList<BaseData>>) throws -> [UInt8] where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
3131
guard root.count > 0 else {
3232
return []
3333
}
@@ -61,7 +61,7 @@ extension StructuredFieldSerializer {
6161
}
6262

6363
extension StructuredFieldSerializer {
64-
private mutating func serializeADictionary<BaseData: RandomAccessCollection>(_ dictionary: OrderedMap<BaseData, ItemOrInnerList<BaseData>>) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
64+
private mutating func serializeADictionary<BaseData: RandomAccessCollection>(_ dictionary: OrderedMap<String, ItemOrInnerList<BaseData>>) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
6565
for (name, value) in dictionary {
6666
try self.serializeAKey(name)
6767

@@ -130,7 +130,7 @@ extension StructuredFieldSerializer {
130130
try self.serializeParameters(item.parameters)
131131
}
132132

133-
private mutating func serializeParameters<BaseData: RandomAccessCollection>(_ parameters: OrderedMap<BaseData, BareItem<BaseData>>) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
133+
private mutating func serializeParameters<BaseData: RandomAccessCollection>(_ parameters: OrderedMap<String, BareItem<BaseData>>) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
134134
for (key, value) in parameters {
135135
self.data.append(asciiSemicolon)
136136
try self.serializeAKey(key)
@@ -145,10 +145,10 @@ extension StructuredFieldSerializer {
145145
}
146146
}
147147

148-
private mutating func serializeAKey<BaseData: RandomAccessCollection>(_ key: BaseData) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
148+
private mutating func serializeAKey(_ key: String) throws {
149149
// We touch each byte twice here, but that's ok: this is cache friendly and less branchy (the copy gets to be memcpy in some cases!)
150150
try key.validateStructuredHeaderKey()
151-
self.data.append(contentsOf: key)
151+
self.data.append(contentsOf: key.utf8)
152152
}
153153

154154
private mutating func serializeABareItem<BaseData: RandomAccessCollection>(_ item: BareItem<BaseData>) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
@@ -193,9 +193,10 @@ extension StructuredFieldSerializer {
193193
}
194194
}
195195

196-
extension RandomAccessCollection where Element == UInt8 {
196+
extension String {
197197
func validateStructuredHeaderKey() throws {
198-
if let firstByte = self.first {
198+
let utf8View = self.utf8
199+
if let firstByte = utf8View.first {
199200
switch firstByte {
200201
case asciiLowercases, asciiAsterisk:
201202
// Good
@@ -205,7 +206,7 @@ extension RandomAccessCollection where Element == UInt8 {
205206
}
206207
}
207208

208-
let validKey = self.dropFirst().allSatisfy {
209+
let validKey = utf8View.dropFirst().allSatisfy {
209210
switch $0 {
210211
case asciiLowercases, asciiDigits, asciiUnderscore,
211212
asciiDash, asciiPeriod, asciiAsterisk:

Tests/StructuredHeadersTests/StructuredFieldParserTests.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ enum FixtureTestError: Error {
2121

2222
final class StructuredFieldParserTests: XCTestCase {
2323
enum TestResult<BaseData: RandomAccessCollection> where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
24-
case dictionary(OrderedMap<BaseData, ItemOrInnerList<BaseData>>)
24+
case dictionary(OrderedMap<String, ItemOrInnerList<BaseData>>)
2525
case list([ItemOrInnerList<BaseData>])
2626
case item(Item<BaseData>)
2727
}
@@ -65,15 +65,15 @@ final class StructuredFieldParserTests: XCTestCase {
6565
}
6666
}
6767

68-
private func _validateParameters<BaseData: RandomAccessCollection>(_ parameters: OrderedMap<BaseData, BareItem<BaseData>>, against schema: JSONSchema, fixtureName: String) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
68+
private func _validateParameters<BaseData: RandomAccessCollection>(_ parameters: OrderedMap<String, BareItem<BaseData>>, against schema: JSONSchema, fixtureName: String) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
6969
guard case .dictionary(let expectedParameters) = schema else {
7070
XCTFail("\(fixtureName): Expected parameters to be a JSON dictionary, but got \(schema)")
7171
return
7272
}
7373
XCTAssertEqual(expectedParameters.count, parameters.count, "\(fixtureName): Different numbers of parameters: expected \(expectedParameters), got \(parameters)")
7474
for (name, value) in parameters {
75-
guard let expectedValue = expectedParameters[String(decoding: name, as: UTF8.self)] else {
76-
XCTFail("\(fixtureName): Did not contain parameter for \(String(decoding: name, as: UTF8.self))")
75+
guard let expectedValue = expectedParameters[name] else {
76+
XCTFail("\(fixtureName): Did not contain parameter for \(name)")
7777
return
7878
}
7979
try self._validateBareItem(value, against: expectedValue, fixtureName: fixtureName)
@@ -128,16 +128,16 @@ final class StructuredFieldParserTests: XCTestCase {
128128
}
129129
}
130130

131-
private func _validateDictionary<BaseData: RandomAccessCollection>(_ result: OrderedMap<BaseData, ItemOrInnerList<BaseData>>, against schema: JSONSchema, fixtureName: String) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
131+
private func _validateDictionary<BaseData: RandomAccessCollection>(_ result: OrderedMap<String, ItemOrInnerList<BaseData>>, against schema: JSONSchema, fixtureName: String) throws where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
132132
guard case .dictionary(let expectedElements) = schema else {
133133
XCTFail("\(fixtureName): Unexpected dictionary: got \(result), expected \(schema)")
134134
return
135135
}
136136

137137
XCTAssertEqual(expectedElements.count, result.count, "\(fixtureName): Different counts in dictionary: got \(result), expected \(expectedElements)")
138138
for (key, value) in result {
139-
guard let expectedEntry = expectedElements[String(decoding: key, as: UTF8.self)] else {
140-
XCTFail("\(fixtureName): Could not find \(String(decoding: key, as: UTF8.self)) in \(expectedElements)")
139+
guard let expectedEntry = expectedElements[key] else {
140+
XCTFail("\(fixtureName): Could not find \(key) in \(expectedElements)")
141141
return
142142
}
143143
switch value {

Tests/StructuredHeadersTests/StructuredFieldSerializerTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import StructuredHeaders
1717

1818
final class StructuredFieldSerializerTests: XCTestCase {
1919
enum TestResult<BaseData: RandomAccessCollection> where BaseData.Element == UInt8, BaseData.SubSequence == BaseData, BaseData: Hashable {
20-
case dictionary(OrderedMap<BaseData, ItemOrInnerList<BaseData>>)
20+
case dictionary(OrderedMap<String, ItemOrInnerList<BaseData>>)
2121
case list([ItemOrInnerList<BaseData>])
2222
case item(Item<BaseData>)
2323
}
@@ -132,10 +132,10 @@ extension StructuredFieldSerializerTests.TestResult where BaseData == ArraySlice
132132
switch schema {
133133
case .dictionary(let dictionary):
134134
// Top level JSON objects are encoding dictionaries.
135-
var dict = OrderedMap<BaseData, ItemOrInnerList<BaseData>>()
135+
var dict = OrderedMap<String, ItemOrInnerList<BaseData>>()
136136

137137
for (name, value) in dictionary {
138-
dict[ArraySlice(name.utf8)] = try ItemOrInnerList(value)
138+
dict[name] = try ItemOrInnerList(value)
139139
}
140140

141141
self = .dictionary(dict)
@@ -234,7 +234,7 @@ extension BareInnerList where BaseData == ArraySlice<UInt8> {
234234
}
235235
}
236236

237-
extension OrderedMap where Key == ArraySlice<UInt8>, Value == BareItem<ArraySlice<UInt8>> {
237+
extension OrderedMap where Key == String, Value == BareItem<ArraySlice<UInt8>> {
238238
init(parameters: JSONSchema) throws {
239239
guard case .dictionary(let jsonDict) = parameters else {
240240
fatalError("Invalid format for parameters: \(parameters)")
@@ -243,7 +243,7 @@ extension OrderedMap where Key == ArraySlice<UInt8>, Value == BareItem<ArraySlic
243243
self.init()
244244

245245
for (name, value) in jsonDict {
246-
self[ArraySlice(name.utf8)] = try BareItem(value)
246+
self[name] = try BareItem(value)
247247
}
248248
}
249249
}

0 commit comments

Comments
 (0)