@@ -2266,6 +2266,144 @@ pub trait Iterator {
22662266 self . try_fold ( ( ) , check ( f) ) == ControlFlow :: BREAK
22672267 }
22682268
2269+ /// Tests if at least `n` elements of the iterator matches a predicate.
2270+ ///
2271+ /// `at_least()` takes a usize `n` and a closure that returns `true` or `false`. It applies
2272+ /// this closure to each element of the iterator, and if more than `n` of them return
2273+ /// `true`, then so does `at_least()`. If less than `n` of them return `true`, it
2274+ /// returns `false`.
2275+ ///
2276+ /// `at_least()` is short-circuiting; in other words, it will stop processing
2277+ /// as soon as it finds `n` `true`, given that no matter what else happens,
2278+ /// the result will also be `true`.
2279+ ///
2280+ /// An empty iterator returns `false`.
2281+ ///
2282+ /// # Examples
2283+ ///
2284+ /// Basic usage:
2285+ ///
2286+ /// ```
2287+ /// let a = [1, 2, 3];
2288+ ///
2289+ /// assert!(a.iter().at_least(1, |&x| x > 0));
2290+ ///
2291+ /// assert!(!a.iter().at_least(1, |&x| x > 5));
2292+ /// ```
2293+ ///
2294+ /// Stopping at the `n`th `true`:
2295+ ///
2296+ /// ```
2297+ /// let a = vec![1, 2, 3, 4, 5];
2298+ ///
2299+ /// let mut iter = a.iter();
2300+ ///
2301+ /// assert!(iter.at_least(0, |&x| x % 2 == 0));
2302+ /// assert!(iter.at_least(1, |&x| x % 2 == 0));
2303+ /// assert!(iter.at_least(2, |&x| x % 2 == 0));
2304+ /// assert!(!iter.at_least(3, |&x| x % 2 == 0));
2305+ ///
2306+ /// // we can still use `iter`, as there are more elements.
2307+ /// let a = [1, 2, 3];
2308+ /// let mut iter = a.iter();
2309+ /// assert!(iter.at_least(1, |&x| x > 0));
2310+ /// assert_eq!(iter.next(), Some(&2));
2311+ /// ```
2312+ #[ inline]
2313+ #[ unstable( feature = "at_least" , reason = "new API" , issue = "none" ) ]
2314+ fn at_least < F > ( & mut self , n : usize , f : F ) -> bool
2315+ where
2316+ Self : Sized ,
2317+ F : FnMut ( Self :: Item ) -> bool ,
2318+ {
2319+ #[ inline]
2320+ fn check < T > (
2321+ n : usize ,
2322+ mut f : impl FnMut ( T ) -> bool ,
2323+ ) -> impl FnMut ( usize , T ) -> ControlFlow < usize , usize > {
2324+ move |mut i, x| {
2325+ i += f ( x) as usize ;
2326+
2327+ if i < n {
2328+ ControlFlow :: Continue ( i)
2329+ } else {
2330+ ControlFlow :: Break ( i)
2331+ }
2332+ }
2333+ }
2334+
2335+ matches ! ( self . try_fold( 0 , check( n, f) ) , ControlFlow :: Break ( _) )
2336+ }
2337+
2338+ /// Tests if at most `n` elements of the iterator matches a predicate.
2339+ ///
2340+ /// `at_most()` takes a usize `n` and a closure that returns `true` or `false`. It applies
2341+ /// this closure to each element of the iterator, and if less than `n` of them return
2342+ /// `true`, then so does `at_least()`. If more than `n` of them return `true`, it
2343+ /// returns `false`.
2344+ ///
2345+ /// `at_most()` is short-circuiting; in other words, it will stop processing
2346+ /// as soon as it finds `n` `false`, given that no matter what else happens,
2347+ /// the result will also be `false`.
2348+ ///
2349+ /// An empty iterator returns `true`.
2350+ ///
2351+ /// # Examples
2352+ ///
2353+ /// Basic usage:
2354+ ///
2355+ /// ```
2356+ /// let a = [1, 2, 3];
2357+ ///
2358+ /// assert!(a.iter().at_most(1, |&x| x > 3));
2359+ ///
2360+ /// assert!(!a.iter().at_most(1, |&x| x > 0));
2361+ /// ```
2362+ ///
2363+ /// Stopping at the `n + 1`th `true`:
2364+ ///
2365+ /// ```
2366+ /// let a = vec![1, 2, 3, 4, 5];
2367+ ///
2368+ /// let mut iter = a.iter();
2369+ ///
2370+ /// assert!(iter.at_least(0, |&x| x % 2 == 0));
2371+ /// assert!(iter.at_least(1, |&x| x % 2 == 0));
2372+ /// assert!(iter.at_least(2, |&x| x % 2 == 0));
2373+ /// assert!(!iter.at_least(3, |&x| x % 2 == 0));
2374+ ///
2375+ /// // we can still use `iter`, as there are more elements.
2376+ /// let a = [1, 1, 3];
2377+ /// let mut iter = a.iter();
2378+ /// assert!(!iter.at_most(1, |&x| x == 1));
2379+ /// assert_eq!(iter.next(), Some(&3));
2380+ /// ```
2381+ #[ inline]
2382+ #[ unstable( feature = "at_most" , reason = "new API" , issue = "none" ) ]
2383+ fn at_most < F > ( & mut self , n : usize , f : F ) -> bool
2384+ where
2385+ Self : Sized ,
2386+ F : FnMut ( Self :: Item ) -> bool ,
2387+ {
2388+ #[ inline]
2389+ fn check < T > (
2390+ n : usize ,
2391+ mut f : impl FnMut ( T ) -> bool ,
2392+ ) -> impl FnMut ( usize , T ) -> ControlFlow < usize , usize > {
2393+ move |mut i, x| {
2394+ i += f ( x) as usize ;
2395+
2396+ if i <= n {
2397+ ControlFlow :: Continue ( i)
2398+ } else {
2399+ ControlFlow :: Break ( i)
2400+ }
2401+ }
2402+ }
2403+
2404+ matches ! ( self . try_fold( 0 , check( n, f) ) , ControlFlow :: Continue ( _) )
2405+ }
2406+
22692407 /// Searches for an element of an iterator that satisfies a predicate.
22702408 ///
22712409 /// `find()` takes a closure that returns `true` or `false`. It applies
0 commit comments