Iterators
take_while() and skip_while()
The .take_while() and .skip_while() adapters slice the prefix of an iterator based on a predicate FnMut(&Self::Item) -> bool rather than a fixed count.
Signatures and Latching Behavior
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
where
Self: Sized,
P: FnMut(&Self::Item) -> bool;
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
where
Self: Sized,
P: FnMut(&Self::Item) -> bool;
Both adapters are stateful prefix operations that permanently latch once the predicate returns false for the first time:
| Adapter | While Predicate Is true |
First Time Predicate Is false |
Subsequent Elements |
|---|---|---|---|
.take_while(p) |
Yields each item | Consumes that item and returns None |
Never polled; returns None forever |
.skip_while(p) |
Discards each item | Yields that item | Yields all remaining items without calling p again |
Source: [ -3, -1, 4, -2, 5 ]
.take_while(|&x| *x < 0):
✓ ✓ ✕ (stops!)
Output: [ -3, -1 ]
.skip_while(|&x| *x < 0):
✕ ✕ ✓ ──────────> (predicate no longer checked)
Output: [ 4, -2, 5 ]
Extracting Header and Body Sections from a Line Stream
fn main() {
let raw_http = [
"HTTP/1.1 200 OK",
"Content-Type: text/plain",
"",
"Body line 1",
"",
"Body line 3",
];
// 1. Take lines until the first empty separator line:
let headers: Vec<&str> = raw_http
.iter()
.copied()
.take_while(|line| !line.is_empty())
.collect();
// 2. Skip non-empty header lines, then skip the 1 empty separator line:
let body: Vec<&str> = raw_http
.iter()
.copied()
.skip_while(|line| !line.is_empty())
.skip(1)
.collect();
println!("Headers: {headers:?}");
println!("Body: {body:?}");
}
Headers: ["HTTP/1.1 200 OK", "Content-Type: text/plain"]
Body: ["Body line 1", "", "Body line 3"]
Notice that "" inside the body ("Body line 1", "", "Body line 3") is preserved by .skip_while(), because .skip_while() stops checking its predicate as soon as the first empty line is encountered.
Transform-and-Take Prefix with .map_while()
When you want to both transform each item and stop on the first None (combining .map() and .take_while()), use .map_while(f), which takes FnMut(Self::Item) -> Option<B> and yields B until f returns None for the first time.