1use anyhow::{Context, Result};
3use indexmap::IndexSet;
4use std::collections::HashSet;
5
6pub trait IDLike:
8 Eq + std::hash::Hash + std::borrow::Borrow<str> + Clone + std::fmt::Display
9{
10}
11impl<T> IDLike for T where
12 T: Eq + std::hash::Hash + std::borrow::Borrow<str> + Clone + std::fmt::Display
13{
14}
15
16macro_rules! define_id_type {
17 ($name:ident) => {
18 #[derive(
19 Clone, std::hash::Hash, PartialEq, Eq, serde::Deserialize, Debug, serde::Serialize,
20 )]
21 pub struct $name(pub std::rc::Rc<str>);
23
24 impl std::borrow::Borrow<str> for $name {
25 fn borrow(&self) -> &str {
26 &self.0
27 }
28 }
29
30 impl std::fmt::Display for $name {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 write!(f, "{}", self.0)
33 }
34 }
35
36 impl From<&str> for $name {
37 fn from(s: &str) -> Self {
38 $name(std::rc::Rc::from(s))
39 }
40 }
41
42 impl From<String> for $name {
43 fn from(s: String) -> Self {
44 $name(std::rc::Rc::from(s))
45 }
46 }
47
48 impl $name {
49 pub fn new(id: &str) -> Self {
51 $name(std::rc::Rc::from(id))
52 }
53 }
54 };
55}
56pub(crate) use define_id_type;
57
58#[cfg(test)]
59define_id_type!(GenericID);
60
61pub trait HasID<ID: IDLike> {
63 fn get_id(&self) -> &ID;
65}
66
67macro_rules! define_id_getter {
69 ($t:ty, $id_ty:ty) => {
70 impl crate::id::HasID<$id_ty> for $t {
71 fn get_id(&self) -> &$id_ty {
72 &self.id
73 }
74 }
75 };
76}
77pub(crate) use define_id_getter;
78
79pub trait IDCollection<ID: IDLike> {
81 fn get_id_by_str(&self, id: &str) -> Result<ID>;
91
92 fn get_id(&self, id: &ID) -> Result<ID>;
102}
103
104macro_rules! define_id_methods {
105 () => {
106 fn get_id_by_str(&self, id: &str) -> Result<ID> {
107 let found = self
108 .get(id)
109 .with_context(|| format!("Unknown ID {id} found"))?;
110 Ok(found.clone())
111 }
112
113 fn get_id(&self, id: &ID) -> Result<ID> {
114 let found = self
115 .get(id.borrow())
116 .with_context(|| format!("Unknown ID {id} found"))?;
117 Ok(found.clone())
118 }
119 };
120}
121
122impl<ID: IDLike> IDCollection<ID> for HashSet<ID> {
123 define_id_methods!();
124}
125
126impl<ID: IDLike> IDCollection<ID> for IndexSet<ID> {
127 define_id_methods!();
128}