SyntaxStudy
Sign Up
Rust Standard Library Traits: From, Into, Iterator
Rust Beginner 1 min read

Standard Library Traits: From, Into, Iterator

The `From` and `Into` traits provide a standard interface for type conversions. Implementing `From for U` automatically gives you `Into for T` for free. These traits are used pervasively in Rust's standard library and ecosystem — for example, `String::from("hello")`, `.into()` on string literals, and `?` operator error conversions all rely on `From`. Prefer implementing `From` over `Into` because the blanket implementation handles `Into` automatically. The `Iterator` trait is one of Rust's most important abstractions. Any type that implements the single required method `fn next(&mut self) -> Option` gains access to dozens of default methods: `map`, `filter`, `fold`, `collect`, `enumerate`, `zip`, `chain`, `take`, `skip`, `any`, `all`, `find`, `flat_map`, and more. These compose into powerful, lazy, zero-overhead data processing pipelines. Making your own type iterable requires implementing `Iterator` directly or implementing `IntoIterator`, which defines how the type converts into an iterator. `for item in collection` is syntactic sugar for calling `IntoIterator::into_iter` and then repeatedly calling `next`. The standard library implements `IntoIterator` for all its collection types in both owned and borrowed forms.
Example
// From / Into
#[derive(Debug)]
struct Celsius(f64);

#[derive(Debug)]
struct Fahrenheit(f64);

impl From<Celsius> for Fahrenheit {
    fn from(c: Celsius) -> Self {
        Fahrenheit(c.0 * 9.0 / 5.0 + 32.0)
    }
}

// Custom iterator
struct Counter {
    count: u32,
    max: u32,
}

impl Counter {
    fn new(max: u32) -> Self { Counter { count: 0, max } }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<u32> {
        if self.count < self.max {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

fn main() {
    // From / Into
    let boiling = Celsius(100.0);
    let f: Fahrenheit = boiling.into();   // uses Into (auto-impl from From)
    println!("100°C = {:?}", f);

    let freezing = Fahrenheit::from(Celsius(0.0));
    println!("0°C = {:?}", freezing);

    // Custom iterator — all the adapter methods are available for free
    let counter = Counter::new(5);
    let sum: u32 = counter.sum();
    println!("sum 1..=5 = {sum}");

    let pairs: Vec<_> = Counter::new(3)
        .zip(Counter::new(3).skip(1))
        .collect();
    println!("zipped pairs: {:?}", pairs);

    // Iterator pipeline on a Vec
    let words = vec!["hello", "world", "rust", "is", "great"];
    let long_caps: Vec<String> = words.iter()
        .filter(|w| w.len() > 3)
        .map(|w| w.to_uppercase())
        .collect();
    println!("long words: {:?}", long_caps);
}