@@ -23,7 +23,7 @@ public struct Generator<ResultValue, ShrinkSequence: SendableSequenceType>: Send
2323
2424 /// Generate a single result, before mapping or filtering.
2525 @usableFromInline
26- internal var _runIntermediate : @Sendable ( inout any SeededRandomNumberGenerator ) -> sending InputValue
26+ internal var _runIntermediate : @Sendable ( inout any SeededRandomNumberGenerator , Int ) throws -> sending InputValue
2727
2828 /// Map an intermediate result to its final value, or return `nil` if the value should be filtered.
2929 @usableFromInline
@@ -33,22 +33,27 @@ public struct Generator<ResultValue, ShrinkSequence: SendableSequenceType>: Send
3333 internal var _shrinker : @Sendable ( InputValue ) -> ShrinkSequence
3434
3535 /// Run the generator until a single unfiltered value is found.
36- @inlinable
37- internal func runFull< G: SeededRandomNumberGenerator > ( _ rng: inout G )
36+ @usableFromInline
37+ internal func runFull< G: SeededRandomNumberGenerator > ( _ rng: inout G , _ limit: Int )
38+ throws
3839 -> sending (
3940 input: InputValue , result: ResultValue
4041 )
4142 {
4243 var arng : any SeededRandomNumberGenerator = rng
4344 defer { rng = arng as! G }
4445
45- while true {
46- let run = _runIntermediate ( & arng)
46+ var attempts = 0
47+
48+ while attempts <= limit {
49+ let run = try _runIntermediate ( & arng, limit)
4750
4851 if let ret = _mapFilter ( run) {
4952 return ( run, ret)
5053 }
54+ attempts += 1
5155 }
56+ throw GeneratorError . runLimitExceeded ( limit)
5257 }
5358}
5459
@@ -57,7 +62,22 @@ extension Generator {
5762 /// - Parameter rng: The random number generator to use.
5863 /// - Returns: A randomly generated value.
5964 public func run< G: SeededRandomNumberGenerator > ( using rng: inout G ) -> sending ResultValue {
60- runFull ( & rng) . result
65+ try ! runFull ( & rng, Int . max) . result
66+ }
67+
68+ /// Generate a single value within a certain amount of attempts.
69+ /// - Parameter rng: The random number generator to use.
70+ /// - Parameter limit: The maximum amount of attempts before the generator stops.
71+ /// - Returns: A randomly generated value.
72+ /// - Throws: When the limit is reached.
73+ public func run< G: SeededRandomNumberGenerator > ( using rng: inout G , limit: Int )
74+ throws ( GeneratorError) -> sending ResultValue
75+ {
76+ do {
77+ return try runFull ( & rng, limit) . result
78+ } catch {
79+ throw error as! GeneratorError
80+ }
6181 }
6282
6383 /// Remove the shrinker for this generator.
@@ -100,7 +120,7 @@ extension Generator where InputValue == ResultValue {
100120 run: @Sendable @escaping ( inout any SeededRandomNumberGenerator ) -> sending ResultValue,
101121 shrink: @Sendable @escaping ( InputValue ) -> sending ShrinkSequence,
102122 ) {
103- self . _runIntermediate = run
123+ _runIntermediate = { rng , _ in run ( & rng ) }
104124 self . _shrinker = shrink
105125 self . _mapFilter = { $0 }
106126 }
@@ -109,7 +129,7 @@ extension Generator where InputValue == ResultValue {
109129extension Generator {
110130 @inlinable
111131 internal init (
112- run: @Sendable @escaping ( inout any SeededRandomNumberGenerator ) -> sending InputValue,
132+ run: @Sendable @escaping ( inout any SeededRandomNumberGenerator , Int ) throws -> sending InputValue,
113133 shrink: @Sendable @escaping ( InputValue ) -> ShrinkSequence ,
114134 finalResult: @Sendable @escaping ( InputValue ) -> ResultValue ?
115135 ) {
@@ -128,7 +148,7 @@ extension Generator where ShrinkSequence == Shrink.None<ResultValue> {
128148 public init (
129149 run: @Sendable @escaping ( inout any SeededRandomNumberGenerator ) -> sending ResultValue
130150 ) {
131- _runIntermediate = run
151+ _runIntermediate = { rng , _ in run ( & rng ) }
132152 _shrinker = { _ in . init( ) }
133153 _mapFilter = { $0 }
134154 }
@@ -220,11 +240,11 @@ extension Generator {
220240 /// - Returns: A generator of optional values.
221241 public func optional( valueRate: Float = 0.75 ) -> Generator < ResultValue ? , Shrink . WithNil < ShrinkSequence > > {
222242 return . init(
223- run: { rng in
243+ run: { rng, limit in
224244 if Float . random ( in: 0 ..< 1 , using: & rng) >= valueRate {
225245 return nil as InputValue ?
226246 }
227- return self . _runIntermediate ( & rng)
247+ return try self . _runIntermediate ( & rng, limit )
228248 } ,
229249 shrink: { value in
230250 if let value {
@@ -283,8 +303,8 @@ extension Generator {
283303 /// - Returns: A copy of this generator.
284304 @inlinable public func eraseToAny( ) -> Generator < ResultValue , AnySequence < Any > > {
285305 return . init(
286- run: { rng in
287- self . _runIntermediate ( & rng) as Any
306+ run: { rng, limit in
307+ try self . _runIntermediate ( & rng, limit ) as Any
288308 } ,
289309 shrink: {
290310 AnySequence ( _shrinker ( $0 as! InputValue ) . lazy. map { $0 as Any } )
0 commit comments