diff options
Diffstat (limited to 'src/types/path.rs')
| -rw-r--r-- | src/types/path.rs | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/src/types/path.rs b/src/types/path.rs new file mode 100644 index 0000000..1d095cd --- /dev/null +++ b/src/types/path.rs @@ -0,0 +1,37 @@ +use ulid::Ulid; + +use super::ids::AccountId; + +#[derive(Debug, thiserror::Error)] +pub enum PathError { + #[error("path is empty")] + Empty, + #[error("invalid ULID segment: {0}")] + BadSegment(String), +} + +#[derive(Clone)] +pub struct MaterializedPath(String); + +impl MaterializedPath { + pub fn parse(s: &str) -> Result<Self, PathError> { + if s.is_empty() { + return Err(PathError::Empty); + } + for seg in s.split('/') { + Ulid::from_string(seg).map_err(|_| PathError::BadSegment(seg.to_string()))?; + } + Ok(MaterializedPath(s.to_string())) + } + pub fn as_str(&self) -> &str { &self.0 } + pub fn depth(&self) -> usize { self.0.split('/').count() } + pub fn is_ancestor_of(&self, other: &MaterializedPath) -> bool { + other.0.starts_with(&self.0) && other.0.as_bytes().get(self.0.len()) == Some(&b'/') + } + pub fn with_child(&self, id: AccountId) -> MaterializedPath { + MaterializedPath(format!("{}/{}", self.0, id.as_ulid())) + } + pub fn root(id: AccountId) -> MaterializedPath { + MaterializedPath(id.as_ulid().to_string()) + } +} |
