Search code examples
loopsrust

Rust how to create struct during iteration and collect it to Result<Vec<Struct>,Error>


I have a following code that works, and compiles, but i was wondering if its possible to do this just using builder pattern , so instead of for loop in 2nd function i would have .for_each() or w/e

use std::path::PathBuf;

use walkdir::{DirEntry, Error};

fn main() {
    println!("Hello, world!");
    match rewalk(walker()) {
        Ok(v) => v.iter().for_each(|f| println!("{:?}", f.path)),
        Err(_e) => (),
    }
}

fn walker() -> Result<Vec<DirEntry>, Error> {
    walkdir::WalkDir::new("clear")
        .max_depth(1)
        .into_iter()
        .filter(|e| {
            e.as_ref().unwrap().path().is_file() && e.as_ref().unwrap().path().extension().is_some()
        })
        //is it possible to continue to iterate from here
        //and collect Result<Vec<MyStruct>,MyError>
        .collect()
}

fn rewalk(ars: Result<Vec<DirEntry>, Error>) -> Result<Vec<MyStruct>, MyError> {
    let mut ve: Vec<MyStruct> = vec![];
    match ars {
        Ok(e) => {
            for x in e {
                ve.push(MyStruct {
                    path: x.path().to_path_buf(),
                });
            }
            Ok(ve)
        }
        Err(e) => Err(MyError::Io),
    }
}
#[derive(Debug)]
enum MyError {
    Io,
    Fs,
}

struct MyStruct {
    path: PathBuf,
}

So basically where i commented in code, is it possible to accomplish what i did in rewalk() function. Dont mind that i have 2 functions, it can be one, but just as part of example i would like to merge rewalk function, to walker function and have it use builder pattern


Solution

  • You can just replace the filter with

        .filter_map(|it|
            match it {
                Ok(entry) => {
                    let path = entry.path();
                    (path.is_file() && path.extension().is_some()).then(||
                        Ok(MyStruct {
                            path: path.to_path_buf(),
                        })
                    )
                }
                Err(_) => Some(Err(MyError::Io))
            }
        )
    

    have it use builder pattern

    There's no "builder pattern" after you've invoked into_iter.