Search for byte from end up to search_depth with iter

I have a function that takes a slice of bytes and a search depth. I want to start at the end of slice and search for the first newline. Then return everything that appears after that new line as new byte slice over the original. For example:

This is a line\n and this is a another line \n this is ano
this should return a byte slice containing this is ano

This is my attempt using iter.

let pos = buf.iter().rev().take(search_depth).rposition(|b| *b == b'\n')?;
Some(buf[pos..])

However, it does not work correctly. I also tried position(). This function will be called a lot, so I am trying to do it as efficiently as possible while avoiding collecting into a Vec. Any ideas?

ps. I also asked this similar question on reddit https://www.reddit.com/r/rust/comments/xm19si/slice_over_original_bytes_from_iterator/

You're reversing the iterator and then effectively reversing the position again with rposition. You just need to use position and then invert the returned index to use on the buffer.

Playground

fn search(buf: &[u8], search_depth: usize) -> Option<&[u8]> {
    let pos = buf
        .iter()
        .rev()
        .take(search_depth)
        .position(|b| *b == b'\n')?;

    let found = &buf[buf.len() - pos..];
    println!("{:?}", std::str::from_utf8(found));
    Some(found)
}

fn main() {
    let buf = b"This is a line\n and this is a another line \n this is ano";

    assert_eq!(search(buf, 100), Some(b" this is ano".as_slice()));

    assert_eq!(search(&buf[..=18], 100), Some(b" and".as_slice()));

    assert_eq!(search(buf, 17), Some(b" this is ano".as_slice()));
}

There may still be an edge case that's not accounted for there, I'm not entirely sure.

I could have sworn I tried this lol. But it's working now, so maybe I was having an issue somewhere else or something. Thanks!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.