local_fmt_macros_internal/utils/
hierarchy.rs

1/// A simple stack-like structure that can be used to keep track of a hierarchy.
2/// This is useful for keeping track of a hierarchy of items, such as a hierarchy of keys.
3/// # Example
4/// ```rust
5/// use local_fmt_macros_internal::utils::hierarchy::Hierarchy;
6/// let mut hierarchy = Hierarchy::new();
7/// hierarchy.process("a", |h| {
8///     h.process("b", |h| {
9///         assert_eq!(h.join("key"), "a.b.key");
10///    });
11///    assert_eq!(h.join("key"), "a.key");
12/// });
13///
14/// assert_eq!(hierarchy.join("key"), "key");
15pub struct Hierarchy<I> {
16    items: Vec<I>,
17}
18
19impl<I> Default for Hierarchy<I> {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl<I> Hierarchy<I> {
26    pub fn new() -> Self {
27        Hierarchy { items: Vec::new() }
28    }
29
30    /// Process an item and a function that takes a mutable reference to the hierarchy.
31    /// The item is pushed onto the hierarchy before the function is called and popped off after the function is called.
32    /// Example usage of [Hierarchy]
33    pub fn process<T>(&mut self, item: I, func: impl FnOnce(&mut Self) -> T) -> T {
34        self.items.push(item);
35        let t = func(self);
36        self.items.pop();
37        t
38    }
39
40    pub fn as_vec(&self) -> &Vec<I> {
41        &self.items
42    }
43}
44
45impl<I: AsRef<str>> Hierarchy<I> {
46    /// Join the items in the hierarchy with the current item.
47    /// The items are joined with a period.
48    /// The generic type must implement [`AsRef<str>`].
49    ///
50    /// Example usage of [Hierarchy]
51    pub fn join(&self, current: &str) -> String {
52        let mut items = self.items.iter().map(|i| i.as_ref()).collect::<Vec<_>>();
53        items.push(current);
54        items.join(".")
55    }
56}
57
58impl<I: ToString> Hierarchy<I> {
59    /// Join the items in the hierarchy with the current item.
60    /// The items are joined with a period.
61    /// The generic type must implement [ToString].
62    ///
63    /// Similarity Example usage of [Hierarchy]
64    pub fn joining(&self, current: String) -> String {
65        let mut items = self.items.iter().map(|i| i.to_string()).collect::<Vec<_>>();
66        items.push(current);
67        items.join(".")
68    }
69}