use crate::internal::const_str_equal;
use core::any::TypeId;
use core::ops::Index;
use core::slice::Iter;
#[derive(Debug, Clone)]
pub struct Attribute {
pub(crate) name: &'static str,
pub(crate) value: Value,
}
impl Attribute {
pub const fn name(&self) -> &'static str {
self.name
}
pub const fn value(&self) -> &Value {
&self.value
}
pub fn is_type<T: 'static>(&self) -> bool {
match self.value() {
Value::Type(ty) => ty.same_as::<T>(),
_ => false,
}
}
pub fn is_type_id(&self, value: &TypeId) -> bool {
match self.value() {
Value::Type(ty) => &ty.type_id() == value,
_ => false,
}
}
pub const fn is_str(&self, value: &str) -> bool {
match self.value() {
Value::Str(string) => const_str_equal(string, value),
_ => false,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Type(Type),
Str(&'static str),
Bool(bool),
Int(i32),
}
#[derive(Debug, Clone)]
pub struct Type {
pub(crate) type_name_fn: fn() -> &'static str,
pub(crate) type_id: TypeId,
}
impl Type {
pub fn type_name(&self) -> &'static str {
(self.type_name_fn)()
}
pub const fn type_id(&self) -> TypeId {
self.type_id
}
pub fn same_as<T: 'static>(&self) -> bool {
TypeId::of::<T>() == self.type_id()
}
}
impl PartialEq for Type {
fn eq(&self, other: &Self) -> bool {
self.type_id() == other.type_id()
}
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub struct Attributes(&'static [Attribute]);
impl Attributes {
pub(crate) const fn new(attributes: &'static [Attribute]) -> Attributes {
Attributes(attributes)
}
pub const fn len(&self) -> usize {
self.0.len()
}
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub const fn named(&self, name: &str) -> Option<&Attribute> {
let mut index = 0;
while index < self.0.len() {
let attribute = &self.0[index];
if const_str_equal(attribute.name(), name) {
return Some(attribute);
}
index += 1;
}
None
}
pub fn iter(&self) -> Iter<'_, Attribute> {
self.0.iter()
}
}
impl Index<usize> for Attributes {
type Output = Attribute;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl IntoIterator for Attributes {
type Item = &'static Attribute;
type IntoIter = Iter<'static, Attribute>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}