1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2020-2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
public struct HTTPClientHeaders: Sendable {
private var items: [Item]
private var headers: [String: [String]]
public init(_ items: [Item] = []) {
self.items = items
self.headers = items.reduce([String: [String]]()) { partial, item in
var map = partial
// Avoid copy-on-write: remove entry from dictionary before mutating
var values = map.removeValue(forKey: item.name.lowercased()) ?? []
values.append(item.value)
map[item.name.lowercased()] = values
return map
}
}
public func contains(_ name: String) -> Bool {
self.headers[name.lowercased()] != nil
}
public var count: Int {
self.headers.count
}
public mutating func add(name: String, value: String) {
self.add(Item(name: name, value: value))
}
public mutating func add(_ item: Item) {
self.add([item])
}
public mutating func add(_ items: [Item]) {
for item in items {
if self.items.contains(item) {
continue
}
// Avoid copy-on-write: remove entry from dictionary before mutating
var values = self.headers.removeValue(forKey: item.name.lowercased()) ?? []
values.append(item.value)
self.headers[item.name.lowercased()] = values
self.items.append(item)
}
}
public mutating func merge(_ other: HTTPClientHeaders) {
self.add(other.items)
}
public func get(_ name: String) -> [String] {
self.headers[name.lowercased()] ?? []
}
public struct Item: Equatable, Sendable {
let name: String
let value: String
public init(name: String, value: String) {
self.name = name
self.value = value
}
}
}
extension HTTPClientHeaders: Sequence {
public func makeIterator() -> IndexingIterator<[Item]> {
self.items.makeIterator()
}
}
extension HTTPClientHeaders: Equatable {
public static func == (lhs: HTTPClientHeaders, rhs: HTTPClientHeaders) -> Bool {
lhs.headers == rhs.headers
}
}
extension HTTPClientHeaders: ExpressibleByDictionaryLiteral {
public init(dictionaryLiteral elements: (String, String)...) {
self.init(elements.map(Item.init))
}
}
|