hydrate_model/
asset_path.rs1const ROOT_PATH_STR: &str = "db:/";
5const ROOT_PATH: AssetPath = AssetPath(None);
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8pub struct AssetPath(Option<String>);
9
10impl AssetPath {
11 pub fn new(s: &str) -> Self {
12 if !s.starts_with(ROOT_PATH_STR) {
14 panic!("Invalid asset path str");
15 }
16
17 if s.len() == ROOT_PATH_STR.len() {
18 AssetPath(None)
19 } else {
20 AssetPath(Some(s.to_string()))
21 }
22 }
23
24 pub fn root_ref() -> &'static Self {
25 &ROOT_PATH
26 }
27
28 pub fn new_root(name: &str) -> Self {
29 assert!(!name.is_empty());
30 AssetPath(Some(format!("{}://", name)))
31 }
32
33 pub fn join(
34 &self,
35 rhs: &str,
36 ) -> AssetPath {
37 if rhs.is_empty() {
38 return self.clone();
39 }
40
41 assert!(!rhs.starts_with(ROOT_PATH_STR));
43 assert!(!rhs.contains("/"));
44
45 match &self.0 {
46 Some(x) => {
47 if x.ends_with("/") {
48 AssetPath(Some(format!("{}{}", x, rhs)))
49 } else {
50 AssetPath(Some(format!("{}/{}", x, rhs)))
51 }
52 }
53 None => AssetPath(Some(format!("{}{}", ROOT_PATH_STR, rhs))),
54 }
55 }
56
57 pub fn parent_path_and_name(&self) -> Option<(Self, String)> {
58 match &self.0 {
59 None => None, Some(path) => {
61 if let Some(index) = path.rfind("/") {
62 if index >= ROOT_PATH_STR.len() {
63 let parent = AssetPath(Some(path[0..index].to_string()));
65 let name = path[index + 1..].to_string();
66 Some((parent, name))
67 } else {
68 let parent = AssetPath(None);
70 let name = path[ROOT_PATH_STR.len()..].to_string();
71 Some((parent, name))
72 }
73 } else {
74 unimplemented!()
76 }
77 }
78 }
79 }
80
81 pub fn is_root_path(&self) -> bool {
82 return self.0.is_none();
83 }
84
85 pub fn split_components(&self) -> Vec<&str> {
86 match &self.0 {
87 Some(x) => x.split("/").skip(1).collect(),
88 None => vec![],
89 }
90 }
91
92 pub fn as_str(&self) -> &str {
93 self.0.as_ref().map(|x| x.as_str()).unwrap_or(ROOT_PATH_STR)
94 }
95
96 pub fn starts_with(
97 &self,
98 other: &AssetPath,
99 ) -> bool {
100 self.as_str().starts_with(other.as_str())
101 }
102}
103
104impl From<&str> for AssetPath {
105 fn from(s: &str) -> Self {
106 AssetPath::new(s)
107 }
108}
109
110impl From<String> for AssetPath {
111 fn from(s: String) -> Self {
112 AssetPath::new(&s)
113 }
114}