machine_check_common/iir/
path.rs1use serde::{Deserialize, Serialize};
2use std::{fmt::Debug, hash::Hash};
3
4#[derive(Clone, Serialize, Deserialize)]
5pub struct IPath {
6    pub leading_colon: Option<ISpan>,
7    pub segments: Vec<IPathSegment>,
8}
9#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
10pub struct IPathSegment {
11    pub ident: IIdent,
12}
13
14impl IPath {
15    pub fn starts_with_absolute(&self, segments: &[&str]) -> bool {
19        if self.leading_colon.is_none() {
20            return false;
21        }
22        if self.segments.len() < segments.len() {
23            return false;
24        }
25        for (self_segment, other_segment) in self.segments.iter().zip(segments.iter()) {
26            if self_segment.ident.name != *other_segment {
27                return false;
28            }
29        }
30        true
31    }
32
33    pub fn matches_relative(&self, segments: &[&str]) -> bool {
37        if self.leading_colon.is_some() {
38            return false;
39        }
40        if self.segments.len() != segments.len() {
41            return false;
42        }
43        for (self_segment, other_segment) in self.segments.iter().zip(segments.iter()) {
44            if self_segment.ident.name != *other_segment {
45                return false;
46            }
47        }
48        true
49    }
50
51    pub fn from_ident(ident: IIdent) -> Self {
52        IPath {
53            leading_colon: None,
54            segments: vec![IPathSegment { ident }],
55        }
56    }
57
58    pub fn span(&self) -> &ISpan {
59        if let Some(last_segment) = self.segments.last() {
60            &last_segment.ident.span
61        } else {
62            &ISpan::Unspecified
63        }
64    }
65
66    pub fn segments_strs(&self) -> impl Iterator<Item = &str> {
67        self.segments
68            .iter()
69            .map(|segment| segment.ident.name.as_str())
70    }
71
72    pub fn get_ident(&self) -> Option<&IIdent> {
73        if self.leading_colon.is_none() && self.segments.len() == 1 {
74            Some(&self.segments[0].ident)
75        } else {
76            None
77        }
78    }
79}
80
81impl PartialEq for IPath {
82    fn eq(&self, other: &Self) -> bool {
83        self.leading_colon.is_some() == other.leading_colon.is_some()
84            && self.segments == other.segments
85    }
86}
87
88impl Eq for IPath {}
89
90impl Hash for IPath {
91    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
92        let has_leading_colon = self.leading_colon.is_some();
93        has_leading_colon.hash(state);
94        self.segments.hash(state);
95    }
96}
97
98impl Debug for IPath {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        if self.leading_colon.is_some() {
101            f.write_str("::")?;
102        }
103
104        let mut first = true;
105        for segment in &self.segments {
106            if first {
107                first = false;
108            } else {
109                f.write_str("::")?;
110            }
111            f.write_str(&segment.ident.name)?;
112        }
113        Ok(())
114    }
115}
116
117#[derive(Clone, Serialize, Deserialize)]
118pub struct IIdent {
119    name: String,
120    span: ISpan,
121}
122
123impl IIdent {
124    pub fn new(name: String, span: ISpan) -> Self {
125        Self { name, span }
126    }
127
128    pub fn name(&self) -> &str {
129        &self.name
130    }
131
132    pub fn set_name(&mut self, name: String) {
133        self.name = name;
134    }
135
136    pub fn into_path(self) -> IPath {
137        IPath::from_ident(self)
138    }
139
140    pub fn mck_prefixed(&self, prefix: &str) -> IIdent {
141        let orig_ident_str = self.name();
142        let stripped_ident_str = orig_ident_str
144            .strip_prefix("__mck_")
145            .unwrap_or(orig_ident_str);
146
147        IIdent::new(
148            format!("__mck_{}_{}", prefix, stripped_ident_str),
149            self.span.clone(),
150        )
151    }
152}
153
154impl PartialEq for IIdent {
155    fn eq(&self, other: &Self) -> bool {
156        self.name == other.name
158    }
159}
160
161impl Eq for IIdent {}
162
163impl Hash for IIdent {
164    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
165        self.name.hash(state);
169    }
170}
171
172impl PartialOrd for IIdent {
173    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
174        Some(self.cmp(other))
175    }
176}
177
178impl Ord for IIdent {
179    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
180        self.name.cmp(&other.name)
182    }
183}
184
185impl Debug for IIdent {
186    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187        f.write_str(&self.name)
189    }
190}
191
192#[derive(Clone, Serialize, Deserialize)]
193pub enum ISpan {
194    Unspecified, }