1pub use self::display::Style as DisplayStyle;
5use std::borrow::Cow;
6use std::fmt::{self, Debug, Display, Formatter, Write};
7use std::rc::Rc;
8
9mod display;
10mod parsers;
11
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct ParseSymbolError;
14
15#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
16pub struct Symbol<'a> {
17 pub version: Option<u64>,
18 pub path: Rc<Path<'a>>,
19 pub instantiating_crate: Option<Rc<Path<'a>>>,
20 pub vendor_specific_suffix: Option<&'a str>,
21}
22
23impl<'a> Symbol<'a> {
24 #[must_use]
26 pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
27 display::display_path(&self.path, style, 0, true)
28 }
29
30 pub fn parse_from_str(input: &'a str) -> Result<(Self, &'a str), ParseSymbolError> {
39 let input = input
40 .strip_prefix("_R")
41 .or_else(|| input.strip_prefix('R'))
42 .or_else(|| input.strip_prefix("__R"))
43 .ok_or(ParseSymbolError)?;
44
45 parsers::parse_symbol(input).map_err(|()| ParseSymbolError)
46 }
47}
48
49impl Display for Symbol<'_> {
50 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
51 self.display(if f.alternate() {
52 DisplayStyle::Normal
53 } else {
54 DisplayStyle::Long
55 })
56 .fmt(f)
57 }
58}
59
60#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
61pub enum Path<'a> {
62 CrateRoot(Identifier<'a>),
63 InherentImpl {
64 impl_path: ImplPath<'a>,
65 type_: Rc<Type<'a>>,
66 },
67 TraitImpl {
68 impl_path: ImplPath<'a>,
69 type_: Rc<Type<'a>>,
70 trait_: Rc<Path<'a>>,
71 },
72 TraitDefinition {
73 type_: Rc<Type<'a>>,
74 trait_: Rc<Path<'a>>,
75 },
76 Nested {
77 namespace: u8,
78 path: Rc<Path<'a>>,
79 identifier: Identifier<'a>,
80 },
81 Generic {
82 path: Rc<Path<'a>>,
83 generic_args: Vec<GenericArg<'a>>,
84 },
85}
86
87impl Debug for Path<'_> {
88 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
89 struct DebugNamespace(u8);
90
91 impl Debug for DebugNamespace {
92 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
93 f.write_char('b')?;
94 Debug::fmt(&char::from(self.0), f)
95 }
96 }
97
98 match self {
99 Self::CrateRoot(identifier) => f.debug_tuple("CrateRoot").field(identifier).finish(),
100 Self::InherentImpl { impl_path, type_ } => f
101 .debug_struct("InherentImpl")
102 .field("impl_path", impl_path)
103 .field("type_", type_.as_ref())
104 .finish(),
105 Self::TraitImpl {
106 impl_path,
107 type_,
108 trait_,
109 } => f
110 .debug_struct("TraitImpl")
111 .field("impl_path", impl_path)
112 .field("type_", type_.as_ref())
113 .field("trait_", trait_.as_ref())
114 .finish(),
115 Self::TraitDefinition { type_, trait_ } => f
116 .debug_struct("TraitDefinition")
117 .field("type_", type_.as_ref())
118 .field("trait_", trait_.as_ref())
119 .finish(),
120 Self::Nested {
121 namespace,
122 path,
123 identifier,
124 } => f
125 .debug_struct("Nested")
126 .field("namespace", &DebugNamespace(*namespace))
127 .field("path", path.as_ref())
128 .field("identifier", identifier)
129 .finish(),
130 Self::Generic { path, generic_args } => f
131 .debug_struct("Generic")
132 .field("path", path.as_ref())
133 .field("generic_args", &generic_args.as_slice())
134 .finish(),
135 }
136 }
137}
138
139impl Path<'_> {
140 #[must_use]
142 pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
143 display::display_path(self, style, 0, false)
144 }
145}
146
147impl Display for Path<'_> {
148 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
149 self.display(if f.alternate() {
150 DisplayStyle::Normal
151 } else {
152 DisplayStyle::Long
153 })
154 .fmt(f)
155 }
156}
157
158#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
159pub struct ImplPath<'a> {
160 pub disambiguator: u64,
161 pub path: Rc<Path<'a>>,
162}
163
164#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
165pub struct Identifier<'a> {
166 pub disambiguator: u64,
167 pub name: Cow<'a, str>,
168}
169
170impl Identifier<'_> {
171 #[must_use]
173 pub fn display(&self) -> impl Display + '_ {
174 self.name.as_ref()
175 }
176}
177
178impl Display for Identifier<'_> {
179 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
180 self.display().fmt(f)
181 }
182}
183
184#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
185pub enum GenericArg<'a> {
186 Lifetime(u64),
187 Type(Rc<Type<'a>>),
188 Const(Rc<Const<'a>>),
189}
190
191impl GenericArg<'_> {
192 #[must_use]
194 pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
195 display::display_generic_arg(self, style, 0)
196 }
197}
198
199impl Display for GenericArg<'_> {
200 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
201 self.display(if f.alternate() {
202 DisplayStyle::Normal
203 } else {
204 DisplayStyle::Long
205 })
206 .fmt(f)
207 }
208}
209
210#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
211pub enum Type<'a> {
212 Basic(BasicType),
213 Named(Rc<Path<'a>>),
214 Array(Rc<Type<'a>>, Rc<Const<'a>>),
215 Slice(Rc<Type<'a>>),
216 Tuple(Vec<Rc<Type<'a>>>),
217 Ref { lifetime: u64, type_: Rc<Type<'a>> },
218 RefMut { lifetime: u64, type_: Rc<Type<'a>> },
219 PtrConst(Rc<Type<'a>>),
220 PtrMut(Rc<Type<'a>>),
221 Fn(FnSig<'a>),
222 DynTrait { dyn_bounds: DynBounds<'a>, lifetime: u64 },
223}
224
225impl Type<'_> {
226 #[must_use]
228 pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
229 display::display_type(self, style, 0)
230 }
231}
232
233impl Display for Type<'_> {
234 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
235 self.display(if f.alternate() {
236 DisplayStyle::Normal
237 } else {
238 DisplayStyle::Long
239 })
240 .fmt(f)
241 }
242}
243
244#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
245pub enum BasicType {
246 I8,
247 Bool,
248 Char,
249 F64,
250 Str,
251 F32,
252 U8,
253 Isize,
254 Usize,
255 I32,
256 U32,
257 I128,
258 U128,
259 I16,
260 U16,
261 Unit,
262 Ellipsis,
263 I64,
264 U64,
265 Never,
266 Placeholder,
267}
268
269impl BasicType {
270 #[must_use]
272 pub fn display(self) -> impl Display {
273 display::display_basic_type(self)
274 }
275}
276
277impl Display for BasicType {
278 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
279 self.display().fmt(f)
280 }
281}
282
283#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
284pub struct FnSig<'a> {
285 pub bound_lifetimes: u64,
286 pub is_unsafe: bool,
287 pub abi: Option<Abi<'a>>,
288 pub argument_types: Vec<Rc<Type<'a>>>,
289 pub return_type: Rc<Type<'a>>,
290}
291
292impl FnSig<'_> {
293 #[must_use]
295 pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
296 display::display_fn_sig(self, style, 0)
297 }
298}
299
300impl Display for FnSig<'_> {
301 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
302 self.display(if f.alternate() {
303 DisplayStyle::Normal
304 } else {
305 DisplayStyle::Long
306 })
307 .fmt(f)
308 }
309}
310
311#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
312pub enum Abi<'a> {
313 C,
314 Named(Cow<'a, str>),
315}
316
317#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
318pub struct DynBounds<'a> {
319 pub bound_lifetimes: u64,
320 pub dyn_traits: Vec<DynTrait<'a>>,
321}
322
323#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
324pub struct DynTrait<'a> {
325 pub path: Rc<Path<'a>>,
326 pub dyn_trait_assoc_bindings: Vec<DynTraitAssocBinding<'a>>,
327}
328
329#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
330pub struct DynTraitAssocBinding<'a> {
331 pub name: Cow<'a, str>,
332 pub type_: Rc<Type<'a>>,
333}
334
335#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
336pub enum Const<'a> {
337 I8(i8),
338 U8(u8),
339 Isize(isize),
340 Usize(usize),
341 I32(i32),
342 U32(u32),
343 I128(i128),
344 U128(u128),
345 I16(i16),
346 U16(u16),
347 I64(i64),
348 U64(u64),
349 Bool(bool),
350 Char(char),
351 Str(String),
352 Ref(Rc<Const<'a>>),
353 RefMut(Rc<Const<'a>>),
354 Array(Vec<Rc<Const<'a>>>),
355 Tuple(Vec<Rc<Const<'a>>>),
356 NamedStruct {
357 path: Rc<Path<'a>>,
358 fields: ConstFields<'a>,
359 },
360 Placeholder,
361}
362
363#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
364pub enum ConstFields<'a> {
365 Unit,
366 Tuple(Vec<Rc<Const<'a>>>),
367 Struct(Vec<(Identifier<'a>, Rc<Const<'a>>)>),
368}
369
370impl Const<'_> {
371 #[must_use]
373 pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
374 display::display_const(self, style, 0, true)
375 }
376}
377
378impl Display for Const<'_> {
379 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
380 self.display(if f.alternate() {
381 DisplayStyle::Normal
382 } else {
383 DisplayStyle::Long
384 })
385 .fmt(f)
386 }
387}