ufs 0.1.0

ufs embed files and read from disk
Documentation
pub use ufs_macros::bind_dir;

mod errors;
pub use errors::Error;
pub use errors::Result;

mod data;
pub use data::Data;

mod file;
pub use file::File;

mod path;
pub use path::Path;










#[derive(Debug, Clone)]
pub struct UnifiedFS {
    pub total: u64,
    pub files: Vec<file::File>,
}



impl UnifiedFS {

    pub fn walk<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
        let mut s = UnifiedFS { ..Default::default() };
        s.walker(path)?;
        Ok(s)
    }



    pub fn size(&self) -> u64 {
        self.total
    }
                
    pub fn entries(&self) -> &[file::File] {
        &self.files
    }
                
    pub fn count(&self) -> usize {
        self.files.len()
    }
                
    pub fn is_empty(&self) -> bool {
        self.files.is_empty()
    }


                
    pub fn get(&self, path: &str) -> Option<&file::File> {
        self.files.iter().find(|f| f.path.to_str() == path)
    }
                
    pub fn as_str(&self, path: &str) -> Option<&str> {
        self.get(path).and_then(|f| f.content.to_str())
    }
                
    pub fn exists(&self, path: &str) -> bool {
        self.files.iter().any(|f| f.path.to_str() == path)
    }
                
    pub fn from_ext(&self, ext: &str) -> Vec<&file::File> {
        self.files.iter().filter(|f| f.path.ext() == Some(ext)).collect()
    }
                
    pub fn iter(&self) -> std::slice::Iter<'_, file::File> {
        self.files.iter()
    }

}


impl UnifiedFS {
    
    fn walker<P>(&mut self, path: P) -> std::io::Result<()>
    where 
        P: AsRef<std::path::Path>,
    {
        let read_dir = std::fs::read_dir(path)?;

        for dir_entry in read_dir.into_iter().filter_map(|e| e.ok()) {

            if dir_entry.metadata()?.is_dir() {
                self.walker(dir_entry.path())?;
                continue;
            }

            let path = dir_entry.path().display().to_string().replace('\\', "/");

            let efs_path = path::Path::Local(path.into());
            let efs_data = data::Data::Local(std::fs::read(efs_path.to_str())?);
            let size = efs_data.len() as u64;
            let depth = efs_path.depth();

            let meta = efs_path.to_path_buf().metadata()?;

            let epoch = std::time::UNIX_EPOCH;
            
            self.files.push(file::File {
                    path: efs_path,
                    content: efs_data,
                    size: size,
                    created: meta.created()?.duration_since(epoch).unwrap().as_secs(),
                    accessed: meta.accessed()?.duration_since(epoch).unwrap().as_secs(),
                    modified: meta.modified()?.duration_since(epoch).unwrap().as_secs(),
                    depth: depth
            });

            self.total += size;
            
        }
        Ok(())
    }

}



impl Default for UnifiedFS {
    fn default() -> Self {
        Self {
            total: 0,
            files: vec![],
        }
    }
}




impl std::ops::Index<&str> for UnifiedFS {
    type Output = file::File;
    fn index(&self, index: &str) -> &Self::Output {
        self.get(index).expect("file not found")
    }
}




impl<'a> IntoIterator for &'a UnifiedFS {
    type Item = &'a file::File;
    type IntoIter = std::slice::Iter<'a, file::File>;
    fn into_iter(self) -> Self::IntoIter {
        self.files.iter()
    }
}