Reuse function accepting falliable iterator of AsRef

Hi,

(note that this is a minimal example, count_u8 is more complex on my use-case)

type Error = &'static str;
type Result<T> = std::result::Result<T, Error>;

fn count_str<A: AsRef<str>, I: Iterator<Item=Result<A>>>(a: I) -> Result<Vec<usize>> {
    let iter = a.map(|x| x.map(|x| x.as_ref().as_bytes()));
    count_u8(iter)
}

fn count_u8<A: AsRef<[u8]>, I: Iterator<Item=Result<A>>>(a: I) -> Result<Vec<usize>> {
    a.map(|x| x.map(|x| x.as_ref().len())).collect()
}

fn main() {
    let a = [Ok("aa"), Ok("bb")];
    let r = count_str(a.into_iter());
    println!("{:?}", r);
}

Is there a mechanism to allow count_u8 to be re-used in the context above? I was hopping to not have to maintain two versions of it (for AsRef<str> and AsRef<[u8]>) or write a macro to just add .as_bytes() depending on whether it is a str or [u8].

The problem here is that x.as_ref().as_bytes() can't outlive x. x is owned because using .as_ref() on result would also make the error a reference - I only want the value to be passed as a ref, not the error itself. :confused:

String and str are AsRef<[u8]>, so you can just:

    let a = [Ok("aa"), Ok("bb")];
    let r = count_u8(a.into_iter());

(Or do you need count_str for some other use case?)

You can do this by wrapping the A: AsRef<str> in a wrapper that implements AsRef<[u8]> by calling .as_ref().as_bytes()

type Error = &'static str;
type Result<T> = std::result::Result<T, Error>;

fn count_str<A: AsRef<str>, I: Iterator<Item=Result<A>>>(a: I) -> Result<Vec<usize>> {
    struct Wrapper<T>(T);
    impl<T: AsRef<str>> AsRef<[u8]> for Wrapper<T> {
        fn as_ref(&self) -> &[u8] {
            self.0.as_ref().as_bytes()
        }
    }
    let iter = a.map(|x| x.map(Wrapper));
    count_u8(iter)
}

fn count_u8<A: AsRef<[u8]>, I: Iterator<Item=Result<A>>>(a: I) -> Result<Vec<usize>> {
    a.map(|x| x.map(|x| x.as_ref().len())).collect()
}

fn main() {
    let a = [Ok("aa"), Ok("bb")];
    let r = count_str(a.into_iter());
    println!("{:?}", r);
}
1 Like