dynamecs_analyze/
span_path.rs1use 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 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 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 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}