jh44tx
jh44tx

Reputation: 119

Returning Error Enumeration with an Arbitrary Variable

I have a function in Rust using try! that attempts to collect all files in a directory recursively and insert them into a vector. Because the function uses try! to check errors, the compiler seems to expect an io::Result return from the function, and doesn't let me include the vector because the try! macro only returns a result. I need the vector to be returned.

Code is as follows:

mod os{
    use std::io;
    use std::fs::{self, DirEntry};
    //use std::fs;
    use std::path::Path;
    // one possible implementation of walking a directory only visiting files
    pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> (io::Result<()>,Vec<String>) {
        let mut filevec: Vec<String> = Vec::new();
        if try!(fs::metadata(dir)).is_dir() {
            for entry in try!(fs::read_dir(dir)) {
                let entry = try!(entry);
                if try!(fs::metadata(entry.path())).is_dir() {
                    try!(visit_dirs(&entry.path(), cb));
                } else {
                    cb(&entry);
                }
            }
        }
        (Ok(()),filevec)

    }
fn push_path_to_vec(p:&DirEntry,v:Vec<String>){
    v.push(p.path().to_str().unwrap().to_string());
}}

Here is the error:

<std macros>:5:8: 6:42 error: mismatched types:
 expected `(core::result::Result<(), std::io::error::Error>, collections::vec::Vec<collections::string::String>)`
    found `core::result::Result<_, _>`
(expected tuple,
    found enum `core::result::Result`) [E0308]

I wonder if there's any idiomatic way to do this that I've missed.

Upvotes: 2

Views: 85

Answers (1)

aochagavia
aochagavia

Reputation: 6246

The return type of visit_dirs is wrong. The function should return a Result, but right now it returns a tuple. Since try! only works for functions returning a Result, your code doesn't compile. You can change the return value of visit_dirs in order to fix it:

pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<Vec<String>>

The new definition means that a Vec<String> will be stored in the Result upon success. With some minor tweaks, the code is accepted by the compiler (see below)

mod os{
    use std::io;
    use std::fs::{self, DirEntry};
    //use std::fs;
    use std::path::Path;
    // one possible implementation of walking a directory only visiting files
    pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<Vec<String>> {
        let mut filevec: Vec<String> = Vec::new();
        if try!(fs::metadata(dir)).is_dir() {
            for entry in try!(fs::read_dir(dir)) {
                let entry = try!(entry);
                if try!(fs::metadata(entry.path())).is_dir() {
                    try!(visit_dirs(&entry.path(), cb));
                } else {
                    cb(&entry);
                }
            }
        }
        Ok(filevec)
    }
fn push_path_to_vec(p:&DirEntry,mut v:Vec<String>){
    v.push(p.path().to_str().unwrap().to_string());
}}

Upvotes: 2

Related Questions