@@ -41,11 +41,11 @@ extension Regex.Match where Output == AnyRegexOutput {
4141 public subscript(
4242 dynamicMember keyPath: KeyPath < ( Substring , _doNotUse: ( ) ) , Substring >
4343 ) -> Substring {
44- input [ range]
44+ anyRegexOutput . input [ range]
4545 }
4646
4747 public subscript( name: String ) -> AnyRegexOutput . Element ? {
48- namedCaptureOffsets [ name] . map { self [ $0 + 1 ] }
48+ anyRegexOutput . namedCaptureOffsets [ name] . map { self [ $0 + 1 ] }
4949 }
5050}
5151
@@ -54,17 +54,19 @@ extension Regex.Match where Output == AnyRegexOutput {
5454public struct AnyRegexOutput {
5555 let input : String
5656 let namedCaptureOffsets : [ String : Int ]
57- fileprivate let _elements : [ ElementRepresentation ]
57+ let _elements : [ ElementRepresentation ]
5858
5959 /// The underlying representation of the element of a type-erased regex
6060 /// output.
61- fileprivate struct ElementRepresentation {
61+ internal struct ElementRepresentation {
6262 /// The depth of `Optioals`s wrapping the underlying value. For example,
6363 /// `Substring` has optional depth `0`, and `Int??` has optional depth `2`.
6464 let optionalDepth : Int
6565
6666 /// The bounds of the output element.
6767 let bounds : Range < String . Index > ?
68+ /// If the output vaule is strongly typed, then this will be set.
69+ var value : Any ? = nil
6870 }
6971}
7072
@@ -75,14 +77,7 @@ extension AnyRegexOutput {
7577 /// Use this initializer to fit a regex with strongly typed captures into the
7678 /// use site of a dynamic regex, like one that was created from a string.
7779 public init < Output> ( _ match: Regex < Output > . Match ) {
78- // Note: We use type equality instead of `match.output as? ...` to prevent
79- // unexpected optional flattening.
80- if Output . self == AnyRegexOutput . self {
81- self = match. output as! AnyRegexOutput
82- return
83- }
84- fatalError ( " FIXME: Not implemented " )
85- // self.init(input: match.input, _elements: <elements of output tuple>)
80+ self = match. anyRegexOutput
8681 }
8782
8883 /// Returns a typed output by converting the underlying value to the specified
@@ -92,11 +87,8 @@ extension AnyRegexOutput {
9287 /// - Returns: The output, if the underlying value can be converted to the
9388 /// output type; otherwise `nil`.
9489 public func `as`< Output> ( _ type: Output . Type = Output . self) -> Output ? {
95- let elements = _elements. map {
96- StructuredCapture (
97- optionalCount: $0. optionalDepth,
98- storedCapture: . init( range: $0. bounds)
99- ) . existentialOutputComponent ( from: input [ ... ] )
90+ let elements = map {
91+ $0. existentialOutputComponent ( from: input [ ... ] )
10092 }
10193 return TypeConstruction . tuple ( of: elements) as? Output
10294 }
@@ -110,7 +102,8 @@ extension AnyRegexOutput {
110102 self . init (
111103 input: input,
112104 namedCaptureOffsets: namedCaptureOffsets,
113- _elements: elements. map ( ElementRepresentation . init) )
105+ _elements: elements. map ( ElementRepresentation . init)
106+ )
114107 }
115108}
116109
@@ -119,7 +112,9 @@ extension AnyRegexOutput.ElementRepresentation {
119112 init ( _ element: StructuredCapture ) {
120113 self . init (
121114 optionalDepth: element. optionalCount,
122- bounds: element. storedCapture. flatMap ( \. range) )
115+ bounds: element. storedCapture. flatMap ( \. range) ,
116+ value: element. storedCapture. flatMap ( \. value)
117+ )
123118 }
124119
125120 func value( forInput input: String ) -> Any {
@@ -142,6 +137,10 @@ extension AnyRegexOutput: RandomAccessCollection {
142137 public struct Element {
143138 fileprivate let representation : ElementRepresentation
144139 let input : String
140+
141+ var optionalDepth : Int {
142+ representation. optionalDepth
143+ }
145144
146145 /// The range over which a value was captured. `nil` for no-capture.
147146 public var range : Range < String . Index > ? {
@@ -155,7 +154,7 @@ extension AnyRegexOutput: RandomAccessCollection {
155154
156155 /// The captured value, `nil` for no-capture
157156 public var value : Any ? {
158- fatalError ( )
157+ representation . value
159158 }
160159 }
161160
@@ -198,19 +197,12 @@ extension Regex.Match where Output == AnyRegexOutput {
198197 /// Use this initializer to fit a regex match with strongly typed captures into the
199198 /// use site of a dynamic regex match, like one that was created from a string.
200199 public init < Output> ( _ match: Regex < Output > . Match ) {
201- fatalError ( " FIXME: Not implemented " )
202- }
203-
204- /// Returns a typed match by converting the underlying values to the specified
205- /// types.
206- ///
207- /// - Parameter type: The expected output type.
208- /// - Returns: A match generic over the output type, if the underlying values
209- /// can be converted to the output type; otherwise, `nil`.
210- public func `as`< Output> (
211- _ type: Output . Type = Output . self
212- ) -> Regex < Output > . Match ? {
213- fatalError ( " FIXME: Not implemented " )
200+ self . init (
201+ anyRegexOutput: match. anyRegexOutput,
202+ range: match. range,
203+ referencedCaptureOffsets: match. referencedCaptureOffsets,
204+ value: match. value
205+ )
214206 }
215207}
216208
0 commit comments