diff --git a/Sources/_StringProcessing/RegexDSL/AnyRegexOutput.swift b/Sources/_StringProcessing/RegexDSL/AnyRegexOutput.swift index 43ab5d3f6..b1d9bfafa 100644 --- a/Sources/_StringProcessing/RegexDSL/AnyRegexOutput.swift +++ b/Sources/_StringProcessing/RegexDSL/AnyRegexOutput.swift @@ -56,6 +56,21 @@ extension AnyRegexOutput { fatalError("FIXME: Not implemented") // self.init(input: match.input, _elements: ) } + + /// Returns a typed output by converting the underlying value to the specified + /// type. + /// - Parameter type: The expected output type. + /// - Returns: The output, if the underlying value can be converted to the + /// output type, or nil otherwise. + public func `as`(_ type: Output.Type) -> Output? { + let elements = _elements.map { + StructuredCapture( + optionalCount: $0.optionalDepth, + storedCapture: .init(range: $0.bounds) + ).existentialOutputComponent(from: input[...]) + } + return TypeConstruction.tuple(of: elements) as? Output + } } extension AnyRegexOutput { diff --git a/Tests/RegexTests/RegexDSLTests.swift b/Tests/RegexTests/RegexDSLTests.swift index b6c6a65d9..4ca446b32 100644 --- a/Tests/RegexTests/RegexDSLTests.swift +++ b/Tests/RegexTests/RegexDSLTests.swift @@ -572,6 +572,12 @@ class RegexDSLTests: XCTestCase { XCTAssertTrue(output[1].substring == "A6F0") XCTAssertTrue(output[2].substring == "A6F1") XCTAssertTrue(output[3].substring == "Extend") + let typedOutput = try XCTUnwrap(output.as( + (Substring, Substring, Substring?, Substring).self)) + XCTAssertEqual(typedOutput.0, line[...]) + XCTAssertTrue(typedOutput.1 == "A6F0") + XCTAssertTrue(typedOutput.2 == "A6F1") + XCTAssertTrue(typedOutput.3 == "Extend") } }