1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use std::ffi::OsString;
use std::path::{Path, PathBuf};

use crate::base;
use crate::context::Context;
use crate::error::{Error, Result};

pub fn read<P: AsRef<Path>>(context: &Context, path: P) -> Result<Vec<u8>> {
    let file = context.root().open_file(path.as_ref())?;
    Ok(file.content().into())
}

pub fn read_to_string<P: AsRef<Path>>(context: &Context, path: P) -> Result<String> {
    let bytes = read(context, path)?;
    String::from_utf8(bytes).map_err(|error| Error::FromUtf8Error(error))
}

pub fn read_link<'a, P: AsRef<Path>>(context: &'a Context, path: P) -> Result<PathBuf> {
    context
        .root()
        .open_link(path)
        .map(|link| link.target().into())
}

pub fn read_dir<'a, P: AsRef<Path>>(context: &'a Context, path: P) -> Result<ReadDir<'a>> {
    let path = path.as_ref();
    let dir = context.root().open_dir(path)?;
    Ok(ReadDir {
        root: path.into(),
        dir_iter: dir.iter(),
    })
}

pub struct ReadDir<'a> {
    root: PathBuf,
    dir_iter: base::DirIter<'a>,
}

impl<'a> Iterator for ReadDir<'a> {
    type Item = Result<DirEntry<'a>>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(name) = self.dir_iter.next() {
            return Some(Ok(DirEntry {
                root: self.root.clone(),
                name,
            }));
        }
        None
    }
}

pub struct DirEntry<'a> {
    root: PathBuf,
    name: &'a OsString,
}

impl<'a> DirEntry<'a> {
    pub fn path(&self) -> PathBuf {
        self.root.join(self.file_name())
    }

    pub fn file_name(&self) -> OsString {
        self.name.clone()
    }
}