Skip to content

Commit 49eef87

Browse files
committed
More polish, added doc comments to the new code
1 parent 5b65724 commit 49eef87

File tree

11 files changed

+270
-151
lines changed

11 files changed

+270
-151
lines changed

Sources/OpenAPIRuntime/Conversion/ParameterStyles.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
/// The serialization style used by a parameter.
1616
///
17-
/// Details: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#fixed-fields-10
17+
/// Details: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md#fixed-fields-10
1818
@_spi(Generated) public enum ParameterStyle: Sendable {
1919

2020
/// The form style.
@@ -26,9 +26,10 @@
2626
///
2727
/// Details: https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.2
2828
case simple
29+
2930
/// The deepObject style.
3031
///
31-
/// Details: https://spec.openapis.org/oas/v3.1.0.html#style-values
32+
/// Details: https://spec.openapis.org/oas/v3.0.4.html#style-values
3233
case deepObject
3334
}
3435

Sources/OpenAPIRuntime/URICoder/Common/URICoderConfiguration.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Foundation
1717
/// A bag of configuration values used by the URI encoder and decoder.
1818
struct URICoderConfiguration {
1919

20-
/// A variable expansion style as described by RFC 6570 and OpenAPI 3.0.3.
20+
/// A variable expansion style as described by RFC 6570 and OpenAPI 3.0.4.
2121
enum Style {
2222

2323
/// A style for simple string variable expansion.
@@ -50,7 +50,7 @@ struct URICoderConfiguration {
5050
var style: Style
5151

5252
/// A Boolean value indicating whether the key should be repeated with
53-
/// each value, as described by RFC 6570 and OpenAPI 3.0.3.
53+
/// each value, as described by RFC 6570 and OpenAPI 3.0.4.
5454
var explode: Bool
5555

5656
/// The character used to escape the space character.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftOpenAPIGenerator open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the SwiftOpenAPIGenerator project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
/// A primitive value produced by `URIValueFromNodeDecoder`.
16+
typealias URIDecodedPrimitive = URIParsedValue
17+
18+
/// An array value produced by `URIValueFromNodeDecoder`.
19+
typealias URIDecodedArray = URIParsedValueArray
20+
21+
/// A dictionary value produced by `URIValueFromNodeDecoder`.
22+
typealias URIDecodedDictionary = [Substring: URIParsedValueArray]

Sources/OpenAPIRuntime/URICoder/Common/URIEncodedNode.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ extension URIEncodedNode {
128128
}
129129
}
130130

131-
/// Marks the node as an array, starting of empty.
131+
/// Marks the node as an array, starting as empty.
132132
/// - Throws: If the node is already set to be anything else but an array.
133133
mutating func markAsArray() throws {
134134
switch self {

Sources/OpenAPIRuntime/URICoder/Common/URIParsedNode.swift

Lines changed: 0 additions & 58 deletions
This file was deleted.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftOpenAPIGenerator open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Foundation
16+
17+
/// A component of a `URIParsedKey`.
18+
typealias URIParsedKeyComponent = String.SubSequence
19+
20+
/// A parsed key for a parsed value.
21+
///
22+
/// For example, `foo=bar` in a `form` string would parse the key as `foo` (single component).
23+
/// In an unexploded `form` string `root=foo,bar`, the key would be `root/foo` (two components).
24+
/// In a `simple` string `bar`, the key would be empty (0 components).
25+
struct URIParsedKey: Hashable {
26+
27+
/// The individual string components.
28+
let components: [URIParsedKeyComponent]
29+
30+
/// Creates a new parsed key.
31+
/// - Parameter components: The key components.
32+
init(_ components: [URIParsedKeyComponent]) { self.components = components }
33+
34+
/// A new empty key.
35+
static var empty: Self { .init([]) }
36+
}
37+
38+
/// A primitive value produced by `URIParser`.
39+
typealias URIParsedValue = String.SubSequence
40+
41+
/// An array of primitive values produced by `URIParser`.
42+
typealias URIParsedValueArray = [URIParsedValue]
43+
44+
/// A key-value produced by `URIParser`.
45+
struct URIParsedPair: Equatable {
46+
47+
/// The key of the pair.
48+
///
49+
/// In `foo=bar`, `foo` is the key.
50+
var key: URIParsedKey
51+
52+
/// The value of the pair.
53+
///
54+
/// In `foo=bar`, `bar` is the value.
55+
var value: URIParsedValue
56+
}
57+
58+
/// An array of key-value pairs produced by `URIParser`.
59+
typealias URIParsedPairArray = [URIParsedPair]
60+
61+
// MARK: - Extensions
62+
63+
extension URIParsedKey: CustomStringConvertible {
64+
/// A textual representation of this instance.
65+
///
66+
/// Calling this property directly is discouraged. Instead, convert an
67+
/// instance of any type to a string by using the `String(describing:)`
68+
/// initializer. This initializer works with any type, and uses the custom
69+
/// `description` property for types that conform to
70+
/// `CustomStringConvertible`:
71+
///
72+
/// struct Point: CustomStringConvertible {
73+
/// let x: Int, y: Int
74+
///
75+
/// var description: String {
76+
/// return "(\(x), \(y))"
77+
/// }
78+
/// }
79+
///
80+
/// let p = Point(x: 21, y: 30)
81+
/// let s = String(describing: p)
82+
/// print(s)
83+
/// // Prints "(21, 30)"
84+
///
85+
/// The conversion of `p` to a string in the assignment to `s` uses the
86+
/// `Point` type's `description` property.
87+
var description: String {
88+
if components.isEmpty { return "<empty>" }
89+
return components.joined(separator: "/")
90+
}
91+
}

Sources/OpenAPIRuntime/URICoder/Decoding/URIDecoder.swift

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import Foundation
1616

1717
/// A type that decodes a `Decodable` value from an URI-encoded string
18-
/// using the rules from RFC 6570, RFC 1866, and OpenAPI 3.0.3, depending on
18+
/// using the rules from RFC 6570, RFC 1866, and OpenAPI 3.0.4, depending on
1919
/// the configuration.
2020
///
2121
/// [RFC 6570 - Form-style query expansion.](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.8)
@@ -45,6 +45,13 @@ import Foundation
4545
/// | `{list\*}` | `red,green,blue` |
4646
/// | `{keys}` | `semi,%3B,dot,.,comma,%2C` |
4747
/// | `{keys\*}` | `semi=%3B,dot=.,comma=%2C` |
48+
///
49+
/// [OpenAPI 3.0.4 - Deep object expansion.](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md#style-examples)
50+
///
51+
/// | Example Template | Expansion |
52+
/// | ---------------- | ----------------------------------------------------------|
53+
/// | `{?keys\*}` | `?keys%5Bsemi%5D=%3B&keys%5Bdot%5D=.&keys%5Bcomma%5D=%2C` |
54+
///
4855
struct URIDecoder: Sendable {
4956

5057
/// The configuration instructing the decoder how to interpret the raw
@@ -60,27 +67,24 @@ extension URIDecoder {
6067

6168
/// Attempt to decode an object from an URI string.
6269
///
63-
/// Under the hood, `URIDecoder` first parses the string into a
64-
/// `URIParsedNode` using `URIParser`, and then uses
65-
/// `URIValueFromNodeDecoder` to decode the `Decodable` value.
66-
///
6770
/// - Parameters:
6871
/// - type: The type to decode.
6972
/// - key: The key of the decoded value. Only used with certain styles
7073
/// and explode options, ignored otherwise.
7174
/// - data: The URI-encoded string.
7275
/// - Returns: The decoded value.
7376
/// - Throws: An error if decoding fails, for example, due to incompatible data or key.
74-
func decode<T: Decodable>(_ type: T.Type = T.self, forKey key: String = "", from data: Substring) throws -> T {
75-
try withDecoder(from: data, forKey: key) { decoder in try decoder.decodeRoot(type) }
77+
func decode<T: Decodable>(
78+
_ type: T.Type = T.self,
79+
forKey key: String = "",
80+
from data: Substring
81+
) throws -> T {
82+
let decoder = URIValueFromNodeDecoder(data: data, rootKey: key[...], configuration: configuration)
83+
return try decoder.decodeRoot(type)
7684
}
7785

7886
/// Attempt to decode an object from an URI string, if present.
7987
///
80-
/// Under the hood, `URIDecoder` first parses the string into a
81-
/// `URIParsedNode` using `URIParser`, and then uses
82-
/// `URIValueFromNodeDecoder` to decode the `Decodable` value.
83-
///
8488
/// - Parameters:
8589
/// - type: The type to decode.
8690
/// - key: The key of the decoded value. Only used with certain styles
@@ -90,22 +94,8 @@ extension URIDecoder {
9094
/// - Throws: An error if decoding fails, for example, due to incompatible data or key.
9195
func decodeIfPresent<T: Decodable>(_ type: T.Type = T.self, forKey key: String = "", from data: Substring) throws
9296
-> T?
93-
{ try withDecoder(from: data, forKey: key) { decoder in try decoder.decodeRootIfPresent(type) } }
94-
95-
/// Make multiple decode calls on the parsed URI.
96-
///
97-
/// Use to avoid repeatedly reparsing the raw string.
98-
/// - Parameters:
99-
/// - data: The URI-encoded string.
100-
/// - key: The root key to decode.
101-
/// - calls: The closure that contains 0 or more calls to
102-
/// the `decode` method on `URIDecoderImpl`.
103-
/// - Returns: The result of the closure invocation.
104-
/// - Throws: An error if parsing or decoding fails.
105-
func withDecoder<R>(from data: Substring, forKey key: String, calls: (URIValueFromNodeDecoder) throws -> R) throws
106-
-> R
10797
{
10898
let decoder = URIValueFromNodeDecoder(data: data, rootKey: key[...], configuration: configuration)
109-
return try calls(decoder)
99+
return try decoder.decodeRootIfPresent(type)
110100
}
111101
}

0 commit comments

Comments
 (0)