pub use self::display::Style as DisplayStyle;
use std::borrow::Cow;
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::rc::Rc;
mod display;
mod parsers;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ParseSymbolError;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Symbol<'a> {
pub version: Option<u64>,
pub path: Rc<Path<'a>>,
pub instantiating_crate: Option<Rc<Path<'a>>>,
pub vendor_specific_suffix: Option<&'a str>,
}
impl<'a> Symbol<'a> {
#[must_use]
pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
display::display_path(&self.path, style, 0, true)
}
pub fn parse_from_str(input: &'a str) -> Result<(Self, &'a str), ParseSymbolError> {
let input = input
.strip_prefix("_R")
.or_else(|| input.strip_prefix('R'))
.or_else(|| input.strip_prefix("__R"))
.ok_or(ParseSymbolError)?;
parsers::parse_symbol(input).map_err(|()| ParseSymbolError)
}
}
impl Display for Symbol<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display(if f.alternate() {
DisplayStyle::Normal
} else {
DisplayStyle::Long
})
.fmt(f)
}
}
#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Path<'a> {
CrateRoot(Identifier<'a>),
InherentImpl {
impl_path: ImplPath<'a>,
type_: Rc<Type<'a>>,
},
TraitImpl {
impl_path: ImplPath<'a>,
type_: Rc<Type<'a>>,
trait_: Rc<Path<'a>>,
},
TraitDefinition {
type_: Rc<Type<'a>>,
trait_: Rc<Path<'a>>,
},
Nested {
namespace: u8,
path: Rc<Path<'a>>,
identifier: Identifier<'a>,
},
Generic {
path: Rc<Path<'a>>,
generic_args: Vec<GenericArg<'a>>,
},
}
impl Debug for Path<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
struct DebugNamespace(u8);
impl Debug for DebugNamespace {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_char('b')?;
Debug::fmt(&char::from(self.0), f)
}
}
match self {
Self::CrateRoot(identifier) => f.debug_tuple("CrateRoot").field(identifier).finish(),
Self::InherentImpl { impl_path, type_ } => f
.debug_struct("InherentImpl")
.field("impl_path", impl_path)
.field("type_", type_.as_ref())
.finish(),
Self::TraitImpl {
impl_path,
type_,
trait_,
} => f
.debug_struct("TraitImpl")
.field("impl_path", impl_path)
.field("type_", type_.as_ref())
.field("trait_", trait_.as_ref())
.finish(),
Self::TraitDefinition { type_, trait_ } => f
.debug_struct("TraitDefinition")
.field("type_", type_.as_ref())
.field("trait_", trait_.as_ref())
.finish(),
Self::Nested {
namespace,
path,
identifier,
} => f
.debug_struct("Nested")
.field("namespace", &DebugNamespace(*namespace))
.field("path", path.as_ref())
.field("identifier", identifier)
.finish(),
Self::Generic { path, generic_args } => f
.debug_struct("Generic")
.field("path", path.as_ref())
.field("generic_args", &generic_args.as_slice())
.finish(),
}
}
}
impl Path<'_> {
#[must_use]
pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
display::display_path(self, style, 0, false)
}
}
impl Display for Path<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display(if f.alternate() {
DisplayStyle::Normal
} else {
DisplayStyle::Long
})
.fmt(f)
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ImplPath<'a> {
pub disambiguator: u64,
pub path: Rc<Path<'a>>,
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Identifier<'a> {
pub disambiguator: u64,
pub name: Cow<'a, str>,
}
impl Identifier<'_> {
#[must_use]
pub fn display(&self) -> impl Display + '_ {
self.name.as_ref()
}
}
impl Display for Identifier<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display().fmt(f)
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum GenericArg<'a> {
Lifetime(u64),
Type(Rc<Type<'a>>),
Const(Rc<Const<'a>>),
}
impl GenericArg<'_> {
#[must_use]
pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
display::display_generic_arg(self, style, 0)
}
}
impl Display for GenericArg<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display(if f.alternate() {
DisplayStyle::Normal
} else {
DisplayStyle::Long
})
.fmt(f)
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Type<'a> {
Basic(BasicType),
Named(Rc<Path<'a>>),
Array(Rc<Type<'a>>, Rc<Const<'a>>),
Slice(Rc<Type<'a>>),
Tuple(Vec<Rc<Type<'a>>>),
Ref { lifetime: u64, type_: Rc<Type<'a>> },
RefMut { lifetime: u64, type_: Rc<Type<'a>> },
PtrConst(Rc<Type<'a>>),
PtrMut(Rc<Type<'a>>),
Fn(FnSig<'a>),
DynTrait { dyn_bounds: DynBounds<'a>, lifetime: u64 },
}
impl Type<'_> {
#[must_use]
pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
display::display_type(self, style, 0)
}
}
impl Display for Type<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display(if f.alternate() {
DisplayStyle::Normal
} else {
DisplayStyle::Long
})
.fmt(f)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum BasicType {
I8,
Bool,
Char,
F64,
Str,
F32,
U8,
Isize,
Usize,
I32,
U32,
I128,
U128,
I16,
U16,
Unit,
Ellipsis,
I64,
U64,
Never,
Placeholder,
}
impl BasicType {
#[must_use]
pub fn display(self) -> impl Display {
display::display_basic_type(self)
}
}
impl Display for BasicType {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display().fmt(f)
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct FnSig<'a> {
pub bound_lifetimes: u64,
pub is_unsafe: bool,
pub abi: Option<Abi<'a>>,
pub argument_types: Vec<Rc<Type<'a>>>,
pub return_type: Rc<Type<'a>>,
}
impl FnSig<'_> {
#[must_use]
pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
display::display_fn_sig(self, style, 0)
}
}
impl Display for FnSig<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display(if f.alternate() {
DisplayStyle::Normal
} else {
DisplayStyle::Long
})
.fmt(f)
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Abi<'a> {
C,
Named(Cow<'a, str>),
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct DynBounds<'a> {
pub bound_lifetimes: u64,
pub dyn_traits: Vec<DynTrait<'a>>,
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct DynTrait<'a> {
pub path: Rc<Path<'a>>,
pub dyn_trait_assoc_bindings: Vec<DynTraitAssocBinding<'a>>,
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct DynTraitAssocBinding<'a> {
pub name: Cow<'a, str>,
pub type_: Rc<Type<'a>>,
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Const<'a> {
I8(i8),
U8(u8),
Isize(isize),
Usize(usize),
I32(i32),
U32(u32),
I128(i128),
U128(u128),
I16(i16),
U16(u16),
I64(i64),
U64(u64),
Bool(bool),
Char(char),
Str(String),
Ref(Rc<Const<'a>>),
RefMut(Rc<Const<'a>>),
Array(Vec<Rc<Const<'a>>>),
Tuple(Vec<Rc<Const<'a>>>),
NamedStruct {
path: Rc<Path<'a>>,
fields: ConstFields<'a>,
},
Placeholder,
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum ConstFields<'a> {
Unit,
Tuple(Vec<Rc<Const<'a>>>),
Struct(Vec<(Identifier<'a>, Rc<Const<'a>>)>),
}
impl Const<'_> {
#[must_use]
pub fn display(&self, style: DisplayStyle) -> impl Display + '_ {
display::display_const(self, style, 0, true)
}
}
impl Display for Const<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.display(if f.alternate() {
DisplayStyle::Normal
} else {
DisplayStyle::Long
})
.fmt(f)
}
}