use std::fmt::{Display, Formatter, Result as FmtResult};
use crate::schema::NamespaceId;
use super::{Name, Type, TypeEq, Types};
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Ident {
pub ns: Option<NamespaceId>,
pub name: Name,
pub type_: IdentType,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum IdentType {
Type = 0,
Group = 1,
Element = 2,
Attribute = 3,
AttributeGroup = 4,
BuildIn = 5,
Enumeration = 6,
}
#[allow(missing_docs)]
impl Ident {
pub const U8: Self = Self::build_in("u8");
pub const U16: Self = Self::build_in("u16");
pub const U32: Self = Self::build_in("u32");
pub const U64: Self = Self::build_in("u64");
pub const U128: Self = Self::build_in("u128");
pub const USIZE: Self = Self::build_in("usize");
pub const I8: Self = Self::build_in("i8");
pub const I16: Self = Self::build_in("i16");
pub const I32: Self = Self::build_in("i32");
pub const I64: Self = Self::build_in("i64");
pub const I128: Self = Self::build_in("i128");
pub const ISIZE: Self = Self::build_in("isize");
pub const F32: Self = Self::build_in("f32");
pub const F64: Self = Self::build_in("f64");
pub const BOOL: Self = Self::build_in("bool");
pub const STRING: Self = Self::build_in("String");
pub const BUILD_IN: &[Self] = &[
Self::U8,
Self::U16,
Self::U32,
Self::U64,
Self::U128,
Self::USIZE,
Self::I8,
Self::I16,
Self::I32,
Self::I64,
Self::I128,
Self::ISIZE,
Self::F32,
Self::F64,
Self::BOOL,
Self::STRING,
];
}
impl Ident {
#[must_use]
pub fn new(name: Name) -> Self {
Self {
ns: None,
name,
type_: IdentType::Type,
}
}
#[must_use]
pub const fn type_(name: &'static str) -> Self {
Self {
ns: None,
name: Name::named(name),
type_: IdentType::Type,
}
}
#[must_use]
pub const fn build_in(name: &'static str) -> Self {
Self {
ns: None,
name: Name::named(name),
type_: IdentType::BuildIn,
}
}
#[must_use]
pub const fn element(name: &'static str) -> Self {
Self {
ns: None,
name: Name::named(name),
type_: IdentType::Element,
}
}
#[must_use]
pub fn with_ns(mut self, ns: Option<NamespaceId>) -> Self {
self.ns = ns;
self
}
#[must_use]
pub fn with_type(mut self, type_: IdentType) -> Self {
self.type_ = type_;
self
}
#[must_use]
pub fn is_build_in(&self) -> bool {
Ident::BUILD_IN.contains(self)
}
}
impl Display for Ident {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let Self { ns, name, type_ } = self;
match type_ {
IdentType::Type => write!(f, "Type(")?,
IdentType::Group => write!(f, "Group(")?,
IdentType::BuildIn => write!(f, "BuildIn(")?,
IdentType::Element => write!(f, "Element(")?,
IdentType::Attribute => write!(f, "Attribute(")?,
IdentType::AttributeGroup => write!(f, "AttributeGroup(")?,
IdentType::Enumeration => write!(f, "Enumeration(")?,
}
if f.sign_minus() {
write!(f, "{name})")?;
} else if let Some(ns) = ns {
write!(f, "ns={}, name={name})", ns.0)?;
} else {
write!(f, "ns=default, name={name})")?;
}
Ok(())
}
}
impl TypeEq for Ident {
fn type_eq(&self, other: &Self, types: &Types) -> bool {
resolve(types, self) == resolve(types, other)
}
}
fn resolve<'a>(types: &'a Types, ident: &'a Ident) -> &'a Ident {
match types.get(ident) {
Some(Type::Reference(x)) if x.is_single() => resolve(types, &x.type_),
None | Some(_) => ident,
}
}