Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 1 addition & 2 deletions Sources/FoundationEssentials/URL/URLTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ extension URL {
}

// MARK: - Parse
#if FOUNDATION_FRAMEWORK

extension URL.Template {
/// Creates a new template from its text form.
///
Expand Down Expand Up @@ -164,7 +164,6 @@ extension URL.Template {
}
}
}
#endif

// MARK: -

Expand Down
54 changes: 7 additions & 47 deletions Sources/FoundationEssentials/URL/URLTemplate_Expression.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
//
//===----------------------------------------------------------------------===//

#if FOUNDATION_FRAMEWORK
internal import RegexBuilder
#endif

#if canImport(CollectionsInternal)
internal import CollectionsInternal
#elseif canImport(OrderedCollections)
Expand Down Expand Up @@ -82,7 +78,6 @@ extension URL.Template.Expression.Element: CustomStringConvertible {
}
}

#if FOUNDATION_FRAMEWORK
extension URL.Template.Expression {
init(_ input: String) throws {
var remainder = input[...]
Expand All @@ -108,7 +103,7 @@ extension URL.Template.Expression {
let explode: Bool
if let max = match.output.3 {
guard
let m = max.map({ Int($0) })
let m = Int(max)
else { throw URL.Template.InvalidExpression(text: "Invalid maximum length '\(input[match.range])'") }
maximumLength = m
explode = false
Expand Down Expand Up @@ -152,61 +147,26 @@ extension URL.Template {

let operatorRegex: Regex<(Substring, Substring?)>
let separatorRegex: Regex<(Substring)>
let elementRegex: Regex<(Substring, Substring, Substring?, Substring??)>
let uriTemplateRegex: Regex<Regex<(Substring, Regex<OneOrMore<Substring>.RegexOutput>.RegexOutput)>.RegexOutput>
let elementRegex: Regex<(Substring, Substring, Substring?, Substring?)>
let uriTemplateRegex: Regex<(Substring, Substring)>

private init() {
self.operatorRegex = Regex {
Optionally {
Capture {
One(.anyOf("+#./;?&"))
}
}
}
self.operatorRegex = try! Regex(#"([\+#.\/;\?&])?"#)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know if it makes a difference whether you create a Regex this way or the other one that specifies the output type?

init(
    _ pattern: String,
    as outputType: Output.Type = Output.self
) throws

For example would it help the performance since we can bypass parsing the result from AnyOutputRegex?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have no idea if that makes any difference. Happy to change it, if that helps. These are only every created once, though.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm ok with this as-is for now. We can always come back if we find this useful later.

.asciiOnlyWordCharacters()
.asciiOnlyDigits()
.asciiOnlyCharacterClasses()
self.separatorRegex = Regex {
","
}
self.separatorRegex = try! Regex(#","#)
.asciiOnlyWordCharacters()
.asciiOnlyDigits()
.asciiOnlyCharacterClasses()
self.elementRegex = Regex {
Capture {
One(("a"..."z").union("A"..."Z"))
ZeroOrMore(("a"..."z").union("A"..."Z").union("0"..."9").union(.anyOf("_")))
}
Optionally {
Capture {
ChoiceOf {
Regex {
":"
Capture {
ZeroOrMore(.digit)
}
}
"*"
}
}
}
}
self.elementRegex = try! Regex(#"([a-zA-Z][a-zA-Z0-9_]*)(:([0-9]*)|\*)?"#)
.asciiOnlyWordCharacters()
.asciiOnlyDigits()
.asciiOnlyCharacterClasses()
self.uriTemplateRegex = Regex {
"{"
Capture {
OneOrMore {
CharacterClass.any.subtracting(.anyOf("}"))
}
}
"}"
}
self.uriTemplateRegex = try! Regex(#"{([^}]+)}"#)
}
}
}
#endif

// .------------------------------------------------------------------.
// | NUL + . / ; ? & # |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
//
//===----------------------------------------------------------------------===//

#if FOUNDATION_FRAMEWORK
internal import RegexBuilder
#endif

extension String {
/// Convert to NFC and percent-escape.
func normalizedAddingPercentEncoding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import struct Foundation.URL
#endif
import Testing

#if FOUNDATION_FRAMEWORK
@Suite("URL.Template Expression")
private enum ExpressionTests {
private typealias Expression = URL.Template.Expression
private typealias Element = URL.Template.Expression.Element
typealias Expression = URL.Template.Expression
typealias Element = URL.Template.Expression.Element

@Test
static func parsingWithSingleName() throws {
Expand Down Expand Up @@ -277,4 +276,3 @@ private enum ExpressionTests {
#expect((try? Expression(input)) == nil, "Should fail to parse, but not crash.")
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ private var variables: [URL.Template.VariableName: URL.Template.Value] {
]
}

#if FOUNDATION_FRAMEWORK
private func assertReplacing(template: String, result: String, sourceLocation: SourceLocation = #_sourceLocation) {
do {
let t = try #require(URL.Template(template))
Expand Down Expand Up @@ -264,4 +263,3 @@ private enum TemplateTests {
assertReplacing(template: "{&keys*}", result: "&semi=%3B&dot=.&comma=%2C")
}
}
#endif