Extract PNGs embedded in a file
Use expect instead of unwrap. This gives you and your users
a better chance at figuring out what went wrong. It's also one step closer
to good error reporting and handling.
Extract an inner_main that returns a Result and thus allows
you to use try!. main can call that method, pattern match on the
Result, print the failure message, have an exit code, etc.
To start with, return a Result&lt;_, Box&lt;Error&gt;&gt;. Box&lt;Error&gt; is an easy
type to build, and try! can convert to it automatically.
Once you are returning Results, theexpects can be transformed into a
ResultusingOption::ok_or`.
One Rust-specific way to think about splitting up functions is
to constrain mutability. Extracting out loading the file allows the
Vec to be mutable in the smallest possible scope.
It may be over engineering, but creating an iterator to handle
finding the embedded PNGs helps separate concerns. For example, I
didn't originally see that i wasn't part of the main finding
logic. It would also allow you to create more focused unit tests on
just this complicated functionality.
The search algorithm itself isn't super efficient; it doesn't
skip as much data as it could in certain places, it seems to always
scan through to the end of the file. What if your data was
something like SIG ... SIG ... SIG ... EOF?
The magic number 130 for the end position is duplicated.
Use a crate like twoway to do
the heavy lifting of searching for byte substrings. This takes care of a
lot of the annoying details.
The data is sliced for the same range multiple times. Any array access is a tiny bit expensive as it has to do range checks. Doing it once is good for both programmer sanity and for the tiny gain in speed.
Using format! to construct the file name may be more obvious than adding a string slice to a String.




extern crate twoway;

use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::{env, process};

const SIGNATURE: [u8; 8] = [137, 80, 78, 71, 13, 10, 26, 10];
const EOF: [u8; 8] = [73, 69, 78, 68, 174, 66, 96, 130];

fn load_file&lt;P&gt;(path: P) -&gt; Result&lt;Vec&lt;u8&gt;, Box&lt;Error&gt;&gt;
    where P: AsRef&lt;Path&gt;
{
    let mut f = try!(File::open(path));

    let mut buf = Vec::new();
    try!(f.read_to_end(&amp;mut buf));
    Ok(buf)
}

struct EmbeddedPng&lt;'a&gt;(&amp;'a [u8]);

impl&lt;'a&gt; Iterator for EmbeddedPng&lt;'a&gt; {
    type Item = &amp;'a [u8];

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        loop {
            match twoway::rfind_bytes(self.0, &amp;SIGNATURE) {
                None =&gt; return None,
                Some(start_idx) =&gt; {
                    let (before, after) = self.0.split_at(start_idx);
                    self.0 = before;

                    if let Some(end_idx) = twoway::find_bytes(after, &amp;EOF) {
                        let png_data = &amp;after[..end_idx + EOF.len()];
                        return Some(png_data)
                    }
                }
            }
        }
    }
}

fn inner_main() -&gt; Result&lt;(), Box&lt;Error&gt;&gt; {
    let path = try!(env::args().nth(1).ok_or("No filename provided"));
    let buf = try!(load_file(path));

    for (i, png_data) in EmbeddedPng(&amp;buf).enumerate() {
        let fname = format!("{}.png", i);
        let mut f = try!(File::create(fname));
        try!(f.write_all(png_data));
    }

    Ok(())
}

fn main() {
    if let Err(e) = inner_main() {
        println!("{}", e);
        process::exit(1);
    }
}