@@ -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,16 +54,18 @@ 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 /// The bounds of the output element.
6666 let bounds : Range < String . Index > ?
67+ /// If the output vaule is strongly typed, then this will be set.
68+ var value : Any ? = nil
6769 }
6870}
6971
@@ -74,14 +76,7 @@ extension AnyRegexOutput {
7476 /// Use this initializer to fit a regex with strongly typed captures into the
7577 /// use site of a dynamic regex, like one that was created from a string.
7678 public init < Output> ( _ match: Regex < Output > . Match ) {
77- // Note: We use type equality instead of `match.output as? ...` to prevent
78- // unexpected optional flattening.
79- if Output . self == AnyRegexOutput . self {
80- self = match. output as! AnyRegexOutput
81- return
82- }
83- fatalError ( " FIXME: Not implemented " )
84- // self.init(input: match.input, _elements: <elements of output tuple>)
79+ self = match. anyRegexOutput
8580 }
8681
8782 /// Returns a typed output by converting the underlying value to the specified
@@ -91,11 +86,8 @@ extension AnyRegexOutput {
9186 /// - Returns: The output, if the underlying value can be converted to the
9287 /// output type; otherwise `nil`.
9388 public func `as`< Output> ( _ type: Output . Type ) -> Output ? {
94- let elements = _elements. map {
95- StructuredCapture (
96- optionalCount: $0. optionalDepth,
97- storedCapture: . init( range: $0. bounds)
98- ) . existentialOutputComponent ( from: input [ ... ] )
89+ let elements = map {
90+ $0. existentialOutputComponent ( from: input [ ... ] )
9991 }
10092 return TypeConstruction . tuple ( of: elements) as? Output
10193 }
@@ -109,7 +101,8 @@ extension AnyRegexOutput {
109101 self . init (
110102 input: input,
111103 namedCaptureOffsets: namedCaptureOffsets,
112- _elements: elements. map ( ElementRepresentation . init) )
104+ _elements: elements. map ( ElementRepresentation . init)
105+ )
113106 }
114107}
115108
@@ -118,7 +111,9 @@ extension AnyRegexOutput.ElementRepresentation {
118111 init ( _ element: StructuredCapture ) {
119112 self . init (
120113 optionalDepth: element. optionalCount,
121- bounds: element. storedCapture. flatMap ( \. range) )
114+ bounds: element. storedCapture. flatMap ( \. range) ,
115+ value: element. storedCapture. flatMap ( \. value)
116+ )
122117 }
123118
124119 func value( forInput input: String ) -> Any {
@@ -141,6 +136,10 @@ extension AnyRegexOutput: RandomAccessCollection {
141136 public struct Element {
142137 fileprivate let representation : ElementRepresentation
143138 let input : String
139+
140+ var optionalDepth : Int {
141+ representation. optionalDepth
142+ }
144143
145144 /// The range over which a value was captured. `nil` for no-capture.
146145 public var range : Range < String . Index > ? {
@@ -154,7 +153,7 @@ extension AnyRegexOutput: RandomAccessCollection {
154153
155154 /// The captured value, `nil` for no-capture
156155 public var value : Any ? {
157- fatalError ( )
156+ representation . value
158157 }
159158 }
160159
@@ -197,17 +196,12 @@ extension Regex.Match where Output == AnyRegexOutput {
197196 /// Use this initializer to fit a regex match with strongly typed captures into the
198197 /// use site of a dynamic regex match, like one that was created from a string.
199198 public init < Output> ( _ match: Regex < Output > . Match ) {
200- fatalError ( " FIXME: Not implemented " )
201- }
202-
203- /// Returns a typed match by converting the underlying values to the specified
204- /// types.
205- ///
206- /// - Parameter type: The expected output type.
207- /// - Returns: A match generic over the output type, if the underlying values
208- /// can be converted to the output type; otherwise, `nil`.
209- public func `as`< Output> ( _ type: Output . Type ) -> Regex < Output > . Match ? {
210- fatalError ( " FIXME: Not implemented " )
199+ self . init (
200+ anyRegexOutput: match. anyRegexOutput,
201+ range: match. range,
202+ referencedCaptureOffsets: match. referencedCaptureOffsets,
203+ value: match. value
204+ )
211205 }
212206}
213207
0 commit comments