Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,20 @@ let package = Package(
]
)

let availabilityMacros: KeyValuePairs<String, String> = [
"HTTPTypes 1.0": "macOS 10.0",
"HTTPTypes 1.1": "macOS 10.0",
"HTTPTypes 1.2": "macOS 10.0",
"HTTPTypes 1.3": "macOS 10.0",
"HTTPTypes 1.6": "macOS 10.0",
Comment on lines +39 to +43

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should/can we use any AppleOS on the latest tools version?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that only works for 26+. I'm using macOS 10.0, * as a placeholder for "available everywhere".

]

for target in package.targets {
var settings = target.swiftSettings ?? []
settings.append(.enableUpcomingFeature("InternalImportsByDefault"))
settings += availabilityMacros.map { name, value in
.enableExperimentalFeature("AvailabilityMacro=\(name): \(value)")
}
target.swiftSettings = settings
}

Expand Down
6 changes: 6 additions & 0 deletions Sources/HTTPTypes/HTTPField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
///
/// The field name is a case-insensitive but case-preserving ASCII string; the field value is a
/// collection of bytes.
@available(HTTPTypes 1.0, *)
public struct HTTPField: Sendable, Hashable {
/// The strategy for whether the field is indexed in the HPACK or QPACK dynamic table.
public struct DynamicTableIndexingStrategy: Sendable, Hashable {
Expand Down Expand Up @@ -73,6 +74,7 @@ public struct HTTPField: Sendable, Hashable {
/// - name: The HTTP field name.
/// - lenientValue: The HTTP field value. Newlines and NULs are converted into space
/// characters.
@available(HTTPTypes 1.1, *)
public init(name: Name, lenientValue: some Collection<UInt8>) {
self.name = name
self.rawValue = Self.lenientLegalizeValue(ISOLatin1String(lenientValue))
Expand Down Expand Up @@ -213,6 +215,7 @@ public struct HTTPField: Sendable, Hashable {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPField: CustomStringConvertible {
public var description: String {
"\(self.name): \(self.value)"
Expand All @@ -221,12 +224,14 @@ extension HTTPField: CustomStringConvertible {

#if !hasFeature(Embedded)

@available(HTTPTypes 1.0, *)
extension HTTPField: CustomPlaygroundDisplayConvertible {
public var playgroundDescription: Any {
self.description
}
}

@available(HTTPTypes 1.0, *)
extension HTTPField: Codable {
enum CodingKeys: String, CodingKey {
case name
Expand Down Expand Up @@ -265,6 +270,7 @@ extension HTTPField: Codable {

#endif

@available(HTTPTypes 1.0, *)
extension HTTPField {
static func isValidToken(_ token: some StringProtocol) -> Bool {
!token.isEmpty
Expand Down
13 changes: 13 additions & 0 deletions Sources/HTTPTypes/HTTPFieldName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

@available(HTTPTypes 1.0, *)
extension HTTPField {
/// A case-insensitive but case-preserving ASCII string with an allowed character set defined
/// in RFC 9110.
Expand Down Expand Up @@ -56,6 +57,7 @@ extension HTTPField {
///
/// - Parameter name: The name of the HTTP field or the HTTP pseudo header field. It must
/// be lowercased.
@available(HTTPTypes 1.2, *)
public init?(parsed name: String) {
guard !name.isEmpty else {
return nil
Expand Down Expand Up @@ -95,6 +97,7 @@ extension HTTPField {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPField.Name: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(self.canonicalName)
Expand All @@ -105,6 +108,7 @@ extension HTTPField.Name: Hashable {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPField.Name: LosslessStringConvertible {
public var description: String {
self.rawName
Expand All @@ -113,12 +117,14 @@ extension HTTPField.Name: LosslessStringConvertible {

#if !hasFeature(Embedded)

@available(HTTPTypes 1.0, *)
extension HTTPField.Name: CustomPlaygroundDisplayConvertible {
public var playgroundDescription: Any {
self.description
}
}

@available(HTTPTypes 1.0, *)
extension HTTPField.Name: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
Expand Down Expand Up @@ -152,6 +158,7 @@ extension HTTPField.Name: Codable {

#endif

@available(HTTPTypes 1.0, *)
extension HTTPField.Name {
static var method: Self { .init(rawName: ":method", canonicalName: ":method") }
static var scheme: Self { .init(rawName: ":scheme", canonicalName: ":scheme") }
Expand Down Expand Up @@ -261,6 +268,7 @@ extension HTTPField.Name {
/// Available-Dictionary
///
/// https://www.rfc-editor.org/rfc/rfc9842.html
@available(HTTPTypes 1.6, *)
public static var availableDictionary: Self {
.init(rawName: "Available-Dictionary", canonicalName: "available-dictionary")
}
Expand Down Expand Up @@ -346,6 +354,7 @@ extension HTTPField.Name {
/// Dictionary-ID
///
/// https://www.rfc-editor.org/rfc/rfc9842.html
@available(HTTPTypes 1.6, *)
public static var dictionaryID: Self { .init(rawName: "Dictionary-ID", canonicalName: "dictionary-id") }

/// Early-Data
Expand Down Expand Up @@ -455,6 +464,7 @@ extension HTTPField.Name {
/// Proxy-Status
///
/// https://www.rfc-editor.org/rfc/rfc9209.html
@available(HTTPTypes 1.3, *)
public static var proxyStatus: Self { .init(rawName: "Proxy-Status", canonicalName: "proxy-status") }

/// Range
Expand Down Expand Up @@ -535,11 +545,13 @@ extension HTTPField.Name {
/// Traceparent
///
/// https://www.w3.org/TR/trace-context/
@available(HTTPTypes 1.6, *)
public static var traceparent: Self { .init(rawName: "Traceparent", canonicalName: "traceparent") }

/// Tracestate
///
/// https://www.w3.org/TR/trace-context/
@available(HTTPTypes 1.6, *)
public static var tracestate: Self { .init(rawName: "Tracestate", canonicalName: "tracestate") }

/// Trailer
Expand All @@ -560,6 +572,7 @@ extension HTTPField.Name {
/// Use-As-Dictionary
///
/// https://www.rfc-editor.org/rfc/rfc9842.html
@available(HTTPTypes 1.6, *)
public static var useAsDictionary: Self { .init(rawName: "Use-As-Dictionary", canonicalName: "use-as-dictionary") }

/// User-Agent
Expand Down
5 changes: 5 additions & 0 deletions Sources/HTTPTypes/HTTPFields.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Synchronization
///
/// `HTTPFields` adheres to modern HTTP semantics. In particular, the "Cookie" request header field
/// is split into separate header fields by default.
@available(HTTPTypes 1.0, *)
public struct HTTPFields: Sendable, Hashable {
private class _Storage: @unchecked Sendable, Hashable {
var fields: [(field: HTTPField, next: UInt16)] = []
Expand Down Expand Up @@ -290,6 +291,7 @@ public struct HTTPFields: Sendable, Hashable {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPFields: ExpressibleByDictionaryLiteral {
public init(dictionaryLiteral elements: (HTTPField.Name, String)...) {
self.reserveCapacity(elements.count)
Expand All @@ -301,6 +303,7 @@ extension HTTPFields: ExpressibleByDictionaryLiteral {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPFields: RangeReplaceableCollection, RandomAccessCollection, MutableCollection {
public typealias Element = HTTPField
public typealias Index = Int
Expand Down Expand Up @@ -376,12 +379,14 @@ extension HTTPFields: RangeReplaceableCollection, RandomAccessCollection, Mutabl

#if !hasFeature(Embedded)

@available(HTTPTypes 1.0, *)
extension HTTPFields: CustomDebugStringConvertible {
public var debugDescription: String {
self._storage.fields.description
}
}

@available(HTTPTypes 1.0, *)
extension HTTPFields: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
Expand Down
3 changes: 3 additions & 0 deletions Sources/HTTPTypes/HTTPParsedFields.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ extension Array where Element: Equatable {
}
}

@available(HTTPTypes 1.2, *)
extension HTTPRequest {
/// Create an HTTP request with an array of parsed `HTTPField`. The fields must include the
/// necessary request pseudo header fields.
Expand All @@ -207,6 +208,7 @@ extension HTTPRequest {
}
}

@available(HTTPTypes 1.2, *)
extension HTTPResponse {
/// Create an HTTP response with an array of parsed `HTTPField`. The fields must include the
/// necessary response pseudo header fields.
Expand All @@ -222,6 +224,7 @@ extension HTTPResponse {
}
}

@available(HTTPTypes 1.2, *)
extension HTTPFields {
/// Create an HTTP trailer fields with an array of parsed `HTTPField`. The fields must not
/// include any pseudo header fields.
Expand Down
1 change: 1 addition & 0 deletions Sources/HTTPTypes/HTTPRequest+URL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import CoreFoundation
#endif // canImport(CoreFoundation)
#endif // canImport(FoundationEssentials)

@available(HTTPTypes 1.0, *)
extension HTTPRequest {
/// The URL of the request synthesized from the scheme, authority, and path pseudo header
/// fields.
Expand Down
5 changes: 5 additions & 0 deletions Sources/HTTPTypes/HTTPRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
///
/// In a legacy HTTP/1 context, the ":scheme" is ignored and the ":authority" is translated into
/// the "Host" header.
@available(HTTPTypes 1.0, *)
public struct HTTPRequest: Sendable, Hashable {
/// The HTTP request method
public struct Method: Sendable, Hashable, RawRepresentable, LosslessStringConvertible {
Expand Down Expand Up @@ -326,6 +327,7 @@ public struct HTTPRequest: Sendable, Hashable {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPRequest: CustomDebugStringConvertible {
public var debugDescription: String {
"(\(self.pseudoHeaderFields.method.rawValue._storage)) \((self.pseudoHeaderFields.scheme?.value).map { "\($0)://" } ?? "")\(self.pseudoHeaderFields.authority?.value ?? "")\(self.pseudoHeaderFields.path?.value ?? "")"
Expand All @@ -334,6 +336,7 @@ extension HTTPRequest: CustomDebugStringConvertible {

#if !hasFeature(Embedded)

@available(HTTPTypes 1.0, *)
extension HTTPRequest.PseudoHeaderFields: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
Expand Down Expand Up @@ -433,6 +436,7 @@ extension HTTPRequest.PseudoHeaderFields: Codable {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPRequest: Codable {
enum CodingKeys: String, CodingKey {
case pseudoHeaderFields
Expand All @@ -454,6 +458,7 @@ extension HTTPRequest: Codable {

#endif

@available(HTTPTypes 1.0, *)
extension HTTPRequest.Method {
/// GET
///
Expand Down
5 changes: 5 additions & 0 deletions Sources/HTTPTypes/HTTPResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
/// An HTTP response message consisting of the ":status" pseudo header field and header fields.
///
/// Conveniences are provided to access the status code and its reason phrase.
@available(HTTPTypes 1.0, *)
public struct HTTPResponse: Sendable, Hashable {
/// The response status consisting of a 3-digit status code and a reason phrase. The reason
/// phrase is ignored by modern HTTP versions.
Expand Down Expand Up @@ -257,6 +258,7 @@ public struct HTTPResponse: Sendable, Hashable {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPResponse: CustomDebugStringConvertible {
public var debugDescription: String {
"\(self.status)"
Expand All @@ -265,6 +267,7 @@ extension HTTPResponse: CustomDebugStringConvertible {

#if !hasFeature(Embedded)

@available(HTTPTypes 1.0, *)
extension HTTPResponse.PseudoHeaderFields: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
Expand Down Expand Up @@ -310,6 +313,7 @@ extension HTTPResponse.PseudoHeaderFields: Codable {
}
}

@available(HTTPTypes 1.0, *)
extension HTTPResponse: Codable {
enum CodingKeys: String, CodingKey {
case pseudoHeaderFields
Expand Down Expand Up @@ -342,6 +346,7 @@ extension HTTPResponse: Codable {

#endif

@available(HTTPTypes 1.0, *)
extension HTTPResponse.Status {
// MARK: 1xx

Expand Down
1 change: 1 addition & 0 deletions Sources/HTTPTypesFoundation/URLRequest+HTTPTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public import Foundation

#if !os(WASI)

@available(HTTPTypes 1.0, *)
extension URLRequest {
/// Create a `URLRequest` from an `HTTPRequest`.
/// - Parameter httpRequest: The HTTP request to convert from.
Expand Down
1 change: 1 addition & 0 deletions Sources/HTTPTypesFoundation/URLResponse+HTTPTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public import FoundationNetworking

#if !os(WASI)

@available(HTTPTypes 1.0, *)
extension HTTPURLResponse {
/// Create an `HTTPURLResponse` from an `HTTPResponse`.
/// - Parameter httpResponse: The HTTP response to convert from.
Expand Down
3 changes: 3 additions & 0 deletions Sources/HTTPTypesFoundation/URLSession+HTTPTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public import FoundationNetworking

#if !os(WASI)

@available(HTTPTypes 1.0, *)
extension URLSessionTask {
/// The original HTTP request this task was created with.
public var originalHTTPRequest: HTTPRequest? {
Expand All @@ -45,6 +46,7 @@ private enum HTTPTypeConversionError: Error {
#endif

@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
@available(HTTPTypes 1.0, *)
extension URLSession {
/// Convenience method to load data using an `HTTPRequest`; creates and resumes a `URLSessionDataTask` internally.
///
Expand Down Expand Up @@ -149,6 +151,7 @@ extension URLSession {
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
@available(HTTPTypes 1.0, *)
extension URLSession {
/// Convenience method to load data using an `HTTPRequest`; creates and resumes a `URLSessionDataTask` internally.
///
Expand Down
Loading