mirror of
https://github.com/apple/swift-foundation.git
synced 2025-05-23 14:00:14 +08:00
* Initial implementation. * Cleanup and fix normalizedAddingPercentEncoding() * Use failing initializer on URL instead of makeURL() * Add standard copyright header * Mark helper functions as fileprivate * URL.Template.init() needs to be failable * Rename InvalidTemplateExpression → URL.Template.InvalidExpression * Add missing @available * Update copyright header * Convert tests XCTest → Swift Testing * Use UInt8.isValidHexDigit * Use URLParser.swift methods for unreserved + reserved characters * Cleanup normalizedAddingPercentEncoding() * Use String(decoding:as:) * guard & white-space * Cleanup “defer” * Rename files URI… → URL… * Add new files to CMakeLists.txt * Add benchmarks. * Add missing @available, 2 * Fix doc comment. * Remove ExpressibleByStringLiteral conformance for URL.Template.VariableName * Improve documentation comments * Fix for 7b14d0bc62 * Fix doc comment * Do not force unwrap “maximum length”
110 lines
3.5 KiB
Swift
110 lines
3.5 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2025 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if canImport(CollectionsInternal)
|
|
internal import CollectionsInternal
|
|
#elseif canImport(OrderedCollections)
|
|
internal import OrderedCollections
|
|
#elseif canImport(_FoundationCollections)
|
|
internal import _FoundationCollections
|
|
#endif
|
|
|
|
extension URL.Template {
|
|
/// The value of a variable used for expanding a template.
|
|
///
|
|
/// A value can either be some text, a list, or an associate list (a dictionary).
|
|
///
|
|
/// ### Examples
|
|
/// ```swift
|
|
/// let hello: URL.Template.Value = .text("Hello World!")
|
|
/// let list: URL.Template.Value = .list(["red", "green", "blue"])
|
|
/// let keys: URL.Template.Value = .associativeList([
|
|
/// "semi": ";",
|
|
/// "dot": ".",
|
|
/// "comma": ",",
|
|
/// ])
|
|
/// ```
|
|
/// Alternatively, for constants, the `ExpressibleBy…Literal` implementations
|
|
/// can be used, i.e.
|
|
/// ```swift
|
|
/// let hello: URL.Template.Value = "Hello World!"
|
|
/// let list: URL.Template.Value = ["red", "green", "blue"]
|
|
/// let keys: URL.Template.Value = [
|
|
/// "semi": ";",
|
|
/// "dot": ".",
|
|
/// "comma": ",",
|
|
/// ]
|
|
/// ```
|
|
public struct Value: Sendable, Hashable {
|
|
let underlying: Underlying
|
|
}
|
|
}
|
|
|
|
extension URL.Template.Value {
|
|
/// A text value to be used with a ``URL.Template``.
|
|
public static func text(_ text: String) -> URL.Template.Value {
|
|
URL.Template.Value(underlying: .text(text))
|
|
}
|
|
|
|
/// A list value (an array of `String`s) to be used with a ``URL.Template``.
|
|
public static func list(_ list: some Sequence<String>) -> URL.Template.Value {
|
|
URL.Template.Value(underlying: .list(Array(list)))
|
|
}
|
|
|
|
/// An associative list value (ordered key-value pairs) to be used with a ``URL.Template``.
|
|
public static func associativeList(_ list: some Sequence<(key: String, value: String)>) -> URL.Template.Value {
|
|
URL.Template.Value(underlying: .associativeList(OrderedDictionary(uniqueKeysWithValues: list)))
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
extension URL.Template.Value: ExpressibleByStringLiteral {
|
|
public init(stringLiteral value: String) {
|
|
self = .text(value)
|
|
}
|
|
}
|
|
|
|
extension URL.Template.Value: ExpressibleByArrayLiteral {
|
|
public init(arrayLiteral elements: String...) {
|
|
self.init(underlying: .list(elements))
|
|
}
|
|
}
|
|
|
|
extension URL.Template.Value: ExpressibleByDictionaryLiteral {
|
|
public init(dictionaryLiteral elements: (String, String)...) {
|
|
self.init(underlying: .associativeList(OrderedDictionary(uniqueKeysWithValues: elements)))
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
extension URL.Template.Value: CustomStringConvertible {
|
|
public var description: String {
|
|
switch underlying {
|
|
case .text(let v): return v
|
|
case .list(let v): return "\(v)"
|
|
case .associativeList(let v): return "\(v)"
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
extension URL.Template.Value {
|
|
enum Underlying: Sendable, Hashable {
|
|
case text(String)
|
|
case list([String])
|
|
case associativeList(OrderedDictionary<String, String>)
|
|
}
|
|
}
|