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}