Wavefront 3D Obj parser/viewer
fn str_to_vec3(s: &amp;str) -&gt; Option&lt;Vec3&gt; {
    let bits: Vec&lt;&amp;str&gt; = s.split(" ").collect();
    if bits.len() != 3 {
        return None;
    }

    Some(Vec3 {
        x: bits[0].parse().unwrap(),
        y: bits[1].parse().unwrap(),
        z: bits[2].parse().unwrap(),
    })

}


For some errors, you panic (if parsing fails) and for other errors you return None. You really should pick one strategy and stick with it. If you want to avoid panicing it is more idiomatic to return Result than Option when it is an error.

Much of your code repeats the same basic action: split/parse/return. You can combine some of the code with a function like this:

fn split_parse&lt;T: std::str::FromStr&gt;(text: &amp;str, split: &amp;str) -&gt; Result&lt;Vec&lt;T&gt;, T::Err&gt; {
    text.split(split).map(str::parse).collect()
}