#[cfg(feature = "im")]
mod im;
pub mod internal;
#[cfg(feature = "serde")]
mod serde;
use internal::helper_string_non_ascii;
use lazy_static::lazy_static;
pub use ossa_typeable_derive::Typeable;
use sha2::{Digest, Sha256};
use std::fmt;
use crate::internal::{
helper_type_args_count, helper_type_constructor, helper_type_ident, helper_usize,
};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct TypeId([u8; 32]);
impl TypeId {
pub fn new(h: [u8; 32]) -> TypeId {
TypeId(h)
}
pub fn identifier(&self) -> [u8; 32] {
self.0
}
}
impl fmt::Display for TypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "0x")?;
for b in self.0 {
write!(f, "{:02X}", b)?;
}
Ok(())
}
}
impl AsRef<[u8]> for TypeId {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
pub trait Typeable {
fn type_ident() -> TypeId; }
macro_rules! derive_typeable_primitive {
( $type_name: ident ) => {
derive_typeable_primitive!($type_name, $type_name);
};
( $type_name: ident, $mod_name: ident ) => {
mod $mod_name {
use super::*;
lazy_static! {
static ref DERIVED_TYPE_ID: TypeId = {
let mut h = Sha256::new();
helper_type_constructor(&mut h, stringify!($type_name));
TypeId(h.finalize().into())
};
}
impl Typeable for $type_name {
fn type_ident() -> TypeId {
*DERIVED_TYPE_ID
}
}
}
};
}
derive_typeable_primitive!(bool);
derive_typeable_primitive!(char);
derive_typeable_primitive!(u8);
derive_typeable_primitive!(u16);
derive_typeable_primitive!(u32);
derive_typeable_primitive!(u64);
derive_typeable_primitive!(u128);
derive_typeable_primitive!(i8);
derive_typeable_primitive!(i16);
derive_typeable_primitive!(i32);
derive_typeable_primitive!(i64);
derive_typeable_primitive!(i128);
derive_typeable_primitive!(f32);
derive_typeable_primitive!(f64);
derive_typeable_primitive!(String, string);
impl<T: Typeable, const N: usize> Typeable for [T; N] {
fn type_ident() -> TypeId {
let mut h = Sha256::new();
helper_string_non_ascii(&mut h, "[]");
helper_type_args_count(&mut h, 1);
helper_usize(&mut h, N);
helper_type_ident::<T>(&mut h);
TypeId(h.finalize().into())
}
}
impl<T: Typeable> Typeable for Vec<T> {
fn type_ident() -> TypeId {
let mut h = Sha256::new();
helper_type_constructor(&mut h, "Vec");
helper_type_args_count(&mut h, 1);
helper_type_ident::<T>(&mut h);
TypeId(h.finalize().into())
}
}
impl<T: Typeable> Typeable for Option<T> {
fn type_ident() -> TypeId {
let mut h = Sha256::new();
helper_type_constructor(&mut h, "Option");
helper_type_args_count(&mut h, 1);
helper_type_ident::<T>(&mut h);
TypeId(h.finalize().into())
}
}