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
67
use std::path::{Path, PathBuf};

#[derive(PartialEq, Eq)]
pub struct AbsolutePathBuf(PathBuf);

impl AbsolutePathBuf {
    pub fn new(p: PathBuf) -> Option<Self> {
        if p.is_absolute() {
            Some(AbsolutePathBuf(p))
        } else {
            None
        }
    }

    pub fn new_unchecked(p: PathBuf) -> Self {
        debug_assert!(p.is_absolute());
        AbsolutePathBuf(p)
    }

    pub fn as_path_buf(&self) -> &PathBuf {
        &self.0
    }

    pub fn as_absolute_path(&self) -> AbsolutePath<'_> {
        AbsolutePath(&self.0)
    }
}

#[derive(PartialEq, Eq)]
pub struct AbsolutePath<'a>(&'a Path);

impl<'a> AbsolutePath<'a> {
    pub fn new(p: &'a Path) -> Option<Self> {
        if p.is_absolute() {
            Some(AbsolutePath(p))
        } else {
            None
        }
    }

    pub fn new_unchecked(p: &'a Path) -> Self {
        debug_assert!(p.is_absolute());
        AbsolutePath(p)
    }

    pub fn as_path(&self) -> &Path {
        self.0
    }
}

#[cfg(test)]
mod tests {
    use super::AbsolutePathBuf;
    use dirs;
    use std::path::Path;

    #[test]
    fn create_abs_path() {
        let abs = dirs::home_dir().unwrap().join("some").join("path");
        let not_abs = Path::new("some").join("path");
        assert_eq!(
            &abs.clone(),
            AbsolutePathBuf::new(abs).unwrap().as_path_buf()
        );
        assert!(AbsolutePathBuf::new(not_abs).is_none());
    }
}