path_calculate/
calculate.rs1use std::io::{self, ErrorKind};
2use std::env;
3use std::borrow::Cow;
4use std::path::{Component, Path, PathBuf};
5
6use path_absolutize::*;
8
9pub trait Calculate {
11 fn home_dir(&self) -> io::Result<Cow<Path>>;
13
14 fn as_absolute_path(&self) -> io::Result<Cow<Path>>;
16
17 fn relative_root_with(&self, path_b: &Path) -> io::Result<Cow<Path>>;
19
20 fn related_to(&self, src_path: &Path) -> io::Result<Cow<Path>>;
22}
23
24impl Calculate for Path {
25 fn home_dir(&self) -> io::Result<Cow<Path>> {
26 #[allow(deprecated)]
27 let home_dir = env::home_dir().unwrap();
28 if home_dir.to_str().unwrap() == "" {
29 return Err(io::Error::from(ErrorKind::InvalidInput))
31 }
32
33 Ok(Cow::from(home_dir))
34 }
35 fn as_absolute_path(&self) -> io::Result<Cow<Path>> {
36 let mut iters = self.components();
37
38 let first_component = iters.next();
39
40 match first_component {
42 Some(Component::RootDir) => {
43 return self.absolutize()
44 },
45 Some(Component::Normal(dir)) => {
46 if dir.to_str().unwrap() == "~" {} else {return self.absolutize()}
47 },
48 None => {
49 return self.absolutize()
50 }
51 _ => {},
52 }
53
54 let mut path_buf = PathBuf::new();
56
57 let home_dir = self.home_dir()?;
58 let home_iters = home_dir.components();
59 for iter in home_iters {
60 path_buf.push(iter)
61 }
62
63 for iter in iters {
64 path_buf.push(iter)
65 }
66
67 Ok(Cow::from(path_buf))
68 }
69
70 fn relative_root_with(&self, path_b: &Path) -> io::Result<Cow<Path>> {
71 let pa = self.as_absolute_path()?;
73 let pb = path_b.as_absolute_path()?;
74
75 let mut path_buf = PathBuf::new();
77
78 let mut itera = pa.components();
79 let mut iterb = pb.components();
80
81 let first_componenta = itera.next().unwrap();
82 let first_componentb = iterb.next().unwrap();
83
84 if first_componenta == first_componentb {
86 path_buf.push(first_componenta);
87 } else {
88 return Err(io::Error::from(ErrorKind::InvalidInput))
89 }
90
91 for componenta in itera {
92 if let Some(componentb) = iterb.next() {
93 if componenta == componentb {
94 path_buf.push(componenta);
95 } else {
96 break;
97 }
98 }
99 }
100
101 Ok(Cow::from(path_buf))
102 }
103
104 fn related_to(&self, src_path: &Path) -> io::Result<Cow<Path>> {
105 let pa = self.as_absolute_path().unwrap();
109 let pb = src_path.as_absolute_path().unwrap();
110 let relative_root = self.relative_root_with(src_path).unwrap();
111
112 let mut path_buf = PathBuf::new();
113
114 let mut itera = pa.components();
116 let mut iterb = pb.components();
117
118 let iterr = relative_root.components();
119
120 for _item in iterr {
122 itera.next();
123 iterb.next();
124 }
125
126 for _item in iterb {
128 path_buf.push(Component::ParentDir);
129 }
130
131 for item in itera {
133 path_buf.push(item)
134 }
135
136 Ok(Cow::from(path_buf))
137 }
138}
139
140impl Calculate for PathBuf {
141 fn home_dir(&self) -> io::Result<Cow<Path>> {
142 self.as_path().home_dir()
143 }
144
145 fn as_absolute_path(&self) -> io::Result<Cow<Path>> {
146 self.as_path().as_absolute_path()
147 }
148
149 fn relative_root_with(&self, path_b: &Path) -> io::Result<Cow<Path>> {
150 self.as_path().relative_root_with(path_b)
151 }
152
153 fn related_to(&self, src_path: &Path) -> io::Result<Cow<Path>> {
154 self.as_path().related_to(src_path)
155 }
156}