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, }