[][src]Crate iter_transpose

This crate provides the IterTranspose trait that turns an Option<I: IntoIterator> (or Result<I: IntoIterator, E>) into an iterator of Option<I::Item> (or Result<I::Item, E>):

use iter_transpose::IterTranspose;

assert_eq!(
    Some(vec![1, 2, 3]).transpose_into_iter().collect::<Vec<_>>(),
    vec![Some(1), Some(2), Some(3)],
);

assert_eq!(
    Result::<Vec<i32>, ()>::Ok(vec![1, 2, 3])
        .transpose_into_iter()
        .collect::<Vec<_>>(),
    vec![Result::<i32, ()>::Ok(1), Ok(2), Ok(3)]
);

Note: if the value is either None or Err, the iterator will be infinite. You can use take_while_some or take_while_ok to truncate them.

use iter_transpose::IterTranspose;

assert_eq!(
    Option::<Vec<i32>>::None
        .transpose_into_iter()
        .take(5)                // We can take as many as we want.
        .collect::<Vec<_>>(),
    vec![None, None, None, None, None],
);
assert_eq!(
    Result::<Vec<i32>, ()>::Err(())
        .transpose_into_iter()
        .take(5)                // We can take as many as we want.
        .collect::<Vec<_>>(),
    vec![Result::<i32, ()>::Err(()), Err(()), Err(()), Err(()), Err(())],
);

Note that in case of Result<T, E>, it must hold that E: Clone + std::fmt::Debug.

Use Case

The main use case is when there is some optional data loaded separately from the required data, e.g., from another file or other source, and we want to produce either a value or None for each element from the required list, depending on whether the optional data was loaded or not.

#[derive(Debug, PartialEq, Eq)]
struct Item {
    name: &'static str,
    description: Option<&'static str>,
}

fn items(names: Vec<&'static str>, descriptions: Option<Vec<&'static str>>) -> Vec<Item> {
    names
        .into_iter()
        .zip(descriptions.transpose_into_iter())
        .map(|(name, description)| Item { name, description })
        .collect()
}

assert_eq!(
    items(vec!["Alice", "Bob", "Charlie"], None),
    vec![
        Item {
            name: "Alice",
            description: None,
        },
        Item {
            name: "Bob",
            description: None,
        },
        Item {
            name: "Charlie",
            description: None,
        },
    ]
);

assert_eq!(
    items(
        vec!["Alice", "Bob", "Charlie"],
        Some(vec!["in Wonderland", "the builder", "likes chocolate"])
    ),
    vec![
        Item {
            name: "Alice",
            description: Some("in Wonderland"),
        },
        Item {
            name: "Bob",
            description: Some("the builder"),
        },
        Item {
            name: "Charlie",
            description: Some("likes chocolate"),
        },
    ]
);

Other Examples

You can also use this function to iterate over all existing elements. Handy functions are unwrap_while_some for Option and unwrap_while_ok for Result:

assert_eq!(
    Some((0..5))
        .transpose_into_iter()
        .unwrap_while_some()
        .collect::<Vec<_>>(),
    Some((0..5))
        .into_iter()
        .flatten()
        .collect::<Vec<_>>(),
);

Structs

OptionTransposedIter

Result of calling IterTranspose::transpose_into_iter on Option.

ResultTransposedIter

Result of calling IterTranspose::transpose_into_iter on Result.

Traits

IterTranspose

Provides transpose_into_iter function for the implementing structs.