Conditional iterator .chain()

⚓ Rust    📅 2025-07-29    👤 surdeus    👁️ 12      

surdeus

Warning

This post was published 127 days ago. The information described in this article may have changed.

You know how it works: I have some code that does what it is supposed to do but I don't like looking at it... :slight_smile:

While processing a string I need to count a certain number of characters backward, and stop when some specific condition is reached. Then I process the string (except what I took from the end) but I may need the last character popped. .once() to the rescue but I can't use it in a single branch of an if because of the different type in the other branch. Right now I just "append" a fake character and then skip it while processing the string but... :nauseated_face:

Example code below and also on playground.

use std::iter::once;

fn main() {
    let s = "abcdexxx";
    
    // We have some logic here that both shortens `s` from the end and counts
    // the occurences of some characters. When we know we need to stop it is
    // too late and the first usefull character has already been popped. We
    // place it in `e`.
    let mut i = s.chars();
    
    let e = loop {
        // Logic is a bit more complex here, but this should suffice.
        if let Some(c) = i.next_back() {
            if c == 'a' {
                break None;
            }
            if c != 'x' {
                break Some(c);
            }
        }
        else {
            break None;
        }
    };
    
    let s_iter = if let Some(e) = e {
        s.chars().chain(once(e))
    }
    else {
        // Comment the .chain() to make the compiler angry.
        s.chars().chain(once('\0'))
    };
    
    for c in s_iter {
        if c == '\0' {
            continue;
        }
        // Process `c` here.
    }
}

4 posts - 3 participants

Read full topic

🏷️ Rust_feed