1use std::fmt;
2
3use crate::error::NamespaceError;
4
5macro_rules! id_type {
6 ($name:ident, $label:literal) => {
7 #[doc = concat!("Stable ", $label, " identity.")]
8 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
9 pub struct $name(String);
10
11 impl $name {
12 #[doc = concat!("Create a ", $label, " id from non-empty text.")]
13 pub fn new(value: impl Into<String>) -> Result<Self, NamespaceError> {
14 let value = value.into();
15 if value.is_empty() {
16 return Err(NamespaceError::EmptyId { kind: $label });
17 }
18 Ok(Self(value))
19 }
20
21 #[doc = concat!("Borrow the underlying ", $label, " id text.")]
22 pub fn as_str(&self) -> &str {
23 &self.0
24 }
25 }
26
27 impl fmt::Display for $name {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.write_str(&self.0)
30 }
31 }
32 };
33}
34
35id_type!(TreeId, "tree");
36id_type!(CellId, "cell");
37id_type!(DirId, "dir");