config_it/shared/mod.rs
1//! Set of commonly used data structures.
2
3pub mod archive;
4pub mod meta;
5
6use serde::{Deserialize, Serialize};
7use std::hash::Hasher;
8
9macro_rules! id_type {
10 ($(#[doc = $doc:literal])* $id:ident $($args:tt)*) => {
11 $(#[doc = $doc])*
12 #[derive(
13 Debug,
14 Clone,
15 Copy,
16 Hash,
17 PartialEq,
18 Eq,
19 PartialOrd,
20 Ord,
21 derive_more::Display,
22 Serialize,
23 Deserialize
24 $($args)*
25 )]
26 pub struct $id(pub u64);
27 };
28}
29
30id_type!(
31 /// Represents a unique identifier for a storage instance.
32 StorageID,
33 derive_more::From
34);
35id_type!(
36 /// Represents a unique identifier for a path within the archive.
37 ///
38 /// This ID type is a wrapper around a 64-bit unsigned integer and is used to distinguish and
39 /// manage paths in a high-performance manner.
40 ///
41 /// As paths within the archive might be nested and represented hierarchically, having a unique
42 /// ID facilitates efficient operations such as lookup, comparison, and storage.
43 PathHash
44);
45id_type!(
46 /// Represents a unique identifier for a group within the storage.
47 ///
48 /// `GroupID` is primarily used to track, manage, and differentiate between different
49 /// configuration sets registered in storage. Each group is assigned a unique ID, ensuring
50 /// accurate management and operations upon it.
51 ///
52 /// This ID type also supports the `From` trait, which allows seamless conversion from certain
53 /// other types.
54 GroupID,
55 derive_more::From
56);
57id_type!(
58 /// Represents a unique identifier for an individual item or element.
59 ///
60 /// `ItemID` allows for the differentiation and management of individual configuration items
61 /// within the storage or a group. Each item, whether it's a variable, property, or another
62 /// entity, is assigned a unique ID for precise operations and management.
63 ///
64 /// The `From` trait support ensures that `ItemID` can be easily constructed from other relevant
65 /// types.
66 ItemID,
67 derive_more::From
68);
69
70impl PathHash {
71 /// Creates a new `PathHash` by hashing a sequence of path strings.
72 ///
73 /// This function takes an iterable of path strings and sequentially hashes each string to
74 /// produce a unique identifier in the form of `PathHash`. To ensure uniqueness and avoid
75 /// collisions between consecutive paths, a delimiter (`\x03\x00`) is written between each
76 /// hashed string.
77 ///
78 /// # Arguments
79 ///
80 /// * `paths` - An iterable of path strings that need to be hashed together to produce the
81 /// `PathHash`.
82 ///
83 /// # Returns
84 ///
85 /// * A new `PathHash` which represents the hashed value of the concatenated path strings.
86 ///
87 /// # Example
88 ///
89 /// ```
90 /// let path_hash = config_it::shared::PathHash::new(["path1", "path2", "path3"]);
91 /// ```
92 pub fn new<'a>(paths: impl IntoIterator<Item = &'a str>) -> Self {
93 let mut hasher = std::collections::hash_map::DefaultHasher::new();
94 paths.into_iter().for_each(|x| {
95 hasher.write(x.as_bytes());
96 hasher.write(b"\x03\x00"); // delim
97 });
98 Self(hasher.finish())
99 }
100}
101
102impl<'a, T: IntoIterator<Item = &'a str>> From<T> for PathHash {
103 fn from(value: T) -> Self {
104 Self::new(value)
105 }
106}
107
108macro_rules! gen_new_fn {
109 ($type:path) => {
110 impl $type {
111 #[cfg(feature = "config")]
112 pub(crate) fn new_unique_incremental() -> Self {
113 static ID_GEN: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
114 Self(ID_GEN.fetch_add(1, std::sync::atomic::Ordering::Relaxed))
115 }
116 }
117 };
118}
119
120gen_new_fn!(StorageID);
121gen_new_fn!(GroupID);
122gen_new_fn!(ItemID);