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.