dynamecs_analyze/
span_path.rs

1use std::fmt::{Display, Formatter};
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub struct SpanPath {
5    span_names: Vec<String>,
6}
7
8impl SpanPath {
9    pub const fn new(span_names: Vec<String>) -> Self {
10        Self { span_names }
11    }
12
13    pub fn span_name(&self) -> Option<&str> {
14        self.span_names.last().map(String::as_str)
15    }
16
17    pub fn span_names(&self) -> &[String] {
18        self.span_names.as_ref()
19    }
20
21    /// The number of span names that make up this span path.
22    pub fn depth(&self) -> usize {
23        self.span_names.len()
24    }
25
26    pub fn parent(&self) -> Option<SpanPath> {
27        let n = self.span_names().len();
28        (n > 0).then(|| SpanPath::new(self.span_names[0..(n - 1)].to_vec()))
29    }
30
31    pub fn is_parent_of(&self, other: &SpanPath) -> bool {
32        let n = self
33            .span_names()
34            .iter()
35            .zip(other.span_names())
36            .take_while(|(self_name, other_name)| self_name == other_name)
37            .count();
38        n == self.span_names().len() && n + 1 == other.span_names().len()
39    }
40
41    /// Determines if this path is an ancestor of another path.
42    ///
43    /// A path is an ancestor of itself.
44    pub fn is_ancestor_of(&self, other: &SpanPath) -> bool {
45        let n = self
46            .span_names()
47            .iter()
48            .zip(other.span_names())
49            .take_while(|(self_name, other_name)| self_name == other_name)
50            .count();
51        n == self.span_names().len()
52    }
53
54    /// Determines the common ancestor of this path and another path.
55    ///
56    /// A path is an ancestor of itself.
57    pub fn common_ancestor(&self, other: &SpanPath) -> SpanPath {
58        let common_span_names = self
59            .span_names()
60            .iter()
61            .zip(other.span_names())
62            .map_while(|(self_name, other_name)| (self_name == other_name).then(|| self_name))
63            .cloned()
64            .collect();
65        SpanPath::new(common_span_names)
66    }
67
68    pub fn push_span_name(&mut self, span_name: String) {
69        self.span_names.push(span_name);
70    }
71}
72
73impl Display for SpanPath {
74    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
75        if let Some((first, rest)) = self.span_names().split_first() {
76            write!(f, "{first}")?;
77            for name in rest {
78                write!(f, ">{}", name)?;
79            }
80        }
81        Ok(())
82    }
83}