55// SPDX-License-Identifier: Apache-2.0
66//
77
8- public struct Headers : Sendable {
9- public var headers : [ Header ] = [ ]
8+ import class Foundation. NSRecursiveLock
9+
10+ public struct Headers : @unchecked Sendable {
11+ private let lock = NSRecursiveLock ( )
12+
13+ private var _headers : [ Header ] = [ ]
14+ public var headers : [ Header ] {
15+ get { access { $0 } }
16+ set { mutate { $0 = newValue } }
17+ }
18+
19+ private mutating func mutate( _ block: ( inout [ Header ] ) -> Void ) {
20+ lock. lock ( )
21+ defer { lock. unlock ( ) }
22+ block ( & _headers)
23+ }
24+
25+ private func access< T> ( _ block: ( [ Header ] ) throws -> T ) rethrows -> T {
26+ lock. lock ( )
27+ defer { lock. unlock ( ) }
28+ return try block ( _headers)
29+ }
1030
1131 /// Creates an empty instance.
1232 public init ( ) { }
@@ -53,11 +73,13 @@ public struct Headers: Sendable {
5373 /// - Parameters:
5474 /// - header: The `Header` to be added or updated.
5575 public mutating func add( _ header: Header ) {
56- guard let index = headers. index ( of: header. name) else {
57- headers. append ( header)
58- return
76+ mutate { headers in
77+ guard let index = headers. index ( of: header. name) else {
78+ headers. append ( header)
79+ return
80+ }
81+ headers [ index] . value. append ( contentsOf: header. value)
5982 }
60- headers [ index] . value. append ( contentsOf: header. value)
6183 }
6284
6385 /// Case-insensitively updates the value of a `Header` by replacing the values of it or appends a `Header`
@@ -66,11 +88,13 @@ public struct Headers: Sendable {
6688 /// - Parameters:
6789 /// - header: The `Header` to be added or updated.
6890 public mutating func update( _ header: Header ) {
69- guard let index = headers. index ( of: header. name) else {
70- headers. append ( header)
71- return
91+ mutate { headers in
92+ guard let index = headers. index ( of: header. name) else {
93+ headers. append ( header)
94+ return
95+ }
96+ headers. replaceSubrange ( index... index, with: [ header] )
7297 }
73- headers. replaceSubrange ( index... index, with: [ header] )
7498 }
7599
76100 /// Case-insensitively updates the value of a `Header` by replacing the values of it or appends a `Header`
@@ -97,17 +121,20 @@ public struct Headers: Sendable {
97121 ///
98122 /// - Parameters:
99123 /// - headers: The `Headers` object.
100- public mutating func addAll( headers: Headers ) {
101- self . headers. append ( contentsOf: headers. headers)
124+ public mutating func addAll( headers otherHeaders: Headers ) {
125+ mutate { headers in
126+ headers. append ( contentsOf: otherHeaders. headers)
127+ }
102128 }
103129
104130 /// Case-insensitively removes a `Header`, if it exists, from the instance.
105131 ///
106132 /// - Parameter name: The name of the `HTTPHeader` to remove.
107133 public mutating func remove( name: String ) {
108- guard let index = headers. index ( of: name) else { return }
109-
110- headers. remove ( at: index)
134+ mutate { headers in
135+ guard let index = headers. index ( of: name) else { return }
136+ headers. remove ( at: index)
137+ }
111138 }
112139
113140 /// Case-insensitively find a header's values by name.
@@ -116,13 +143,14 @@ public struct Headers: Sendable {
116143 ///
117144 /// - Returns: The values of the header, if they exist.
118145 public func values( for name: String ) -> [ String ] ? {
119- guard let indices = headers. indices ( of: name) , !indices. isEmpty else { return nil }
120- var values = [ String] ( )
121- for index in indices {
122- values. append ( contentsOf: headers [ index] . value)
146+ access { headers in
147+ guard let indices = headers. indices ( of: name) , !indices. isEmpty else { return nil }
148+ var values = [ String] ( )
149+ for index in indices {
150+ values. append ( contentsOf: headers [ index] . value)
151+ }
152+ return values
123153 }
124-
125- return values
126154 }
127155
128156 /// Case-insensitively find a header's value by name.
@@ -131,29 +159,28 @@ public struct Headers: Sendable {
131159 ///
132160 /// - Returns: The value of header as a comma delimited string, if it exists.
133161 public func value( for name: String ) -> String ? {
134- guard let values = values ( for: name) else {
135- return nil
136- }
162+ guard let values = values ( for: name) else { return nil }
137163 return values. joined ( separator: " , " )
138164 }
139165
140166 public func exists( name: String ) -> Bool {
141- headers . index ( of: name) != nil
167+ access { $0 . index ( of: name) != nil }
142168 }
143169
144170 /// The dictionary representation of all headers.
145171 ///
146172 /// This representation does not preserve the current order of the instance.
147173 public var dictionary : [ String : [ String ] ] {
148- let namesAndValues = headers. map { ( $0. name, $0. value) }
149-
150- return Dictionary ( namesAndValues) { ( first, last) -> [ String ] in
151- return first + last
174+ access { headers in
175+ let namesAndValues = headers. map { ( $0. name, $0. value) }
176+ return Dictionary ( namesAndValues) { ( first, last) -> [ String ] in
177+ first + last
178+ }
152179 }
153180 }
154181
155182 public var isEmpty : Bool {
156- return self . headers . isEmpty
183+ access { $0 . isEmpty }
157184 }
158185}
159186
@@ -164,14 +191,18 @@ extension Headers: Equatable {
164191 /// - rhs: The second `Headers` to compare.
165192 /// - Returns: `true` if the two values are equal irrespective of order, otherwise `false`.
166193 public static func == ( lhs: Headers , rhs: Headers ) -> Bool {
167- return lhs. headers. sorted ( ) == rhs. headers. sorted ( )
194+ lhs. access { lhsHeaders in
195+ rhs. access { rhsHeaders in
196+ lhsHeaders. sorted ( ) == rhsHeaders. sorted ( )
197+ }
198+ }
168199 }
169200}
170201
171202extension Headers : Hashable {
172203
173204 public func hash( into hasher: inout Hasher ) {
174- hasher. combine ( headers . sorted ( ) )
205+ access { hasher. combine ( $0 . sorted ( ) ) }
175206 }
176207}
177208
0 commit comments