#[derive(Clone)]
pub struct Path {
paths: Vec<String>,
home: String,
sep: String,
}
impl Path {
pub fn system(path: &str) -> Self {
#[cfg(target_os = "windows")]
let sep = "\\";
#[cfg(not(target_os = "windows"))]
let sep = "/";
Self {
paths: Vec::new(),
sep: sep.to_string(),
home: String::new(),
}
.join(path)
}
pub fn join(&self, path: &str) -> Self {
let mut s = self.clone();
let v = path.split(s.sep.as_str());
for ele in v {
if ele == ".." {
s.paths.pop();
} else if ele == "." {
} else if ele == "~" {
} else {
s.paths.push(ele.to_string());
}
}
s
}
pub fn to_str(&self) -> String {
self.paths.join(&self.sep)
}
pub fn pop(&self) -> Self {
let mut s = self.clone();
s.paths.pop();
s
}
pub fn releative(&self,target:&str)->String{
let mut target = Self::system(target);
let mut out = Vec::new();
out.append(&mut vec!["..".to_string(); self.paths.len()]);
out.append(&mut target.paths);
out.join(&self.sep)
}
}
#[cfg(test)]
mod tests {
use super::Path;
#[test]
fn test() {
let mut path = Path::system("/ok");
path = path.join("1");
assert_eq!("/ok/1", path.to_str());
let mut path = Path::system("/ok");
path = path.join("../1");
assert_eq!("/1", path.to_str());
let mut path = Path::system("res");
path = path.join("../1");
assert_eq!("1", path.to_str());
}
#[test]
fn test_releative_path(){
assert_eq!("../../4/5.png",Path::system("1/2").releative("4/5.png"));
assert_eq!("../../4/5.png",Path::system("4/2").releative("4/5.png"));
assert_eq!("../../4/5/6.png",Path::system("4/2").releative("4/5/6.png"));
assert_eq!("../4/5/6.png",Path::system("2").releative("4/5/6.png"));
}
}