use core::marker::PhantomData;
use std::borrow::Cow;
pub trait TypedId: sealed::SealedId + Copy + Eq + core::hash::Hash + core::fmt::Debug {
type Raw: Copy + Eq + core::hash::Hash + core::fmt::Debug;
fn raw_value(&self) -> Self::Raw;
fn is_zero(&self) -> bool;
}
mod sealed {
pub trait SealedId {}
}
macro_rules! impl_typed_id {
($name:ident, $raw:ty, $zero:expr) => {
impl<K> sealed::SealedId for $name<K> {}
impl<K> TypedId for $name<K> {
type Raw = $raw;
#[inline]
fn raw_value(&self) -> $raw {
self.raw
}
#[inline]
fn is_zero(&self) -> bool {
self.raw == $zero
}
}
};
}
macro_rules! typed_id {
($(#[$meta:meta])* $name:ident, $raw:ty) => {
$(#[$meta])*
#[repr(transparent)]
pub struct $name<K> {
raw: $raw,
_kind: PhantomData<K>,
}
impl<K> $name<K> {
#[doc = concat!("Wraps a raw `", stringify!($raw), "` as a typed [`", stringify!($name), "`].")]
#[doc = concat!("use wasm4pm_compat::ids::", stringify!($name), ";")]
#[doc = concat!("let id = ", stringify!($name), "::<Local>::new(7);")]
#[inline]
pub const fn new(raw: $raw) -> Self {
Self { raw, _kind: PhantomData }
}
#[doc = concat!("Returns the underlying raw `", stringify!($raw), "`.")]
#[doc = concat!("use wasm4pm_compat::ids::", stringify!($name), ";")]
#[doc = concat!("assert_eq!(", stringify!($name), "::<Local>::new(42).raw(), 42);")]
#[inline]
pub const fn raw(self) -> $raw {
self.raw
}
#[doc = concat!("Consumes `self` and returns the underlying raw `", stringify!($raw), "` value.")]
#[doc = concat!("use wasm4pm_compat::ids::", stringify!($name), ";")]
#[doc = concat!("assert_eq!(", stringify!($name), "::<Local>::new(5).into_inner(), 5);")]
#[inline]
pub const fn into_inner(self) -> $raw {
self.raw
}
#[doc = concat!("Borrows the underlying raw `", stringify!($raw), "` value.")]
#[doc = concat!("use wasm4pm_compat::ids::", stringify!($name), ";")]
#[doc = concat!("assert_eq!(*", stringify!($name), "::<Local>::new(9).as_inner(), 9);")]
#[inline]
pub const fn as_inner(&self) -> &$raw {
&self.raw
}
}
impl<K> Clone for $name<K> {
#[inline]
fn clone(&self) -> Self { *self }
}
impl<K> Copy for $name<K> {}
impl<K> PartialEq for $name<K> {
#[inline]
fn eq(&self, other: &Self) -> bool { self.raw == other.raw }
}
impl<K> Eq for $name<K> {}
impl<K> core::hash::Hash for $name<K> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { self.raw.hash(state); }
}
impl<K> core::fmt::Debug for $name<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple(stringify!($name)).field(&self.raw).finish()
}
}
impl<K> core::fmt::Display for $name<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}({})", stringify!($name), self.raw)
}
}
impl<K> PartialOrd for $name<K> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<K> Ord for $name<K> {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.raw.cmp(&other.raw)
}
}
};
}
typed_id!(
#[doc(alias = "event identifier")]
#[doc(alias = "event id")]
EventId, u64
);
typed_id!(
ObjectId, u64
);
typed_id!(
ActivityId, u32
);
typed_id!(
RelationId, u32
);
typed_id!(
TraceId, u64
);
typed_id!(
ObjectTypeId, u32
);
typed_id!(
EventTypeId, u32
);
typed_id!(
CaseId, u64
);
impl_typed_id!(EventId, u64, 0u64);
impl_typed_id!(ObjectId, u64, 0u64);
impl_typed_id!(ActivityId, u32, 0u32);
impl_typed_id!(RelationId, u32, 0u32);
impl_typed_id!(TraceId, u64, 0u64);
impl_typed_id!(ObjectTypeId, u32, 0u32);
impl_typed_id!(EventTypeId, u32, 0u32);
impl_typed_id!(CaseId, u64, 0u64);
pub struct ObjectTypeName<K> {
label: Cow<'static, str>,
_kind: PhantomData<K>,
}
impl<K> ObjectTypeName<K> {
#[inline]
pub fn from_static(label: &'static str) -> Self {
Self {
label: Cow::Borrowed(label),
_kind: PhantomData,
}
}
#[inline]
pub fn from_owned(label: String) -> Self {
Self {
label: Cow::Owned(label),
_kind: PhantomData,
}
}
#[inline]
pub fn as_str(&self) -> &str {
&self.label
}
}
impl<K> Clone for ObjectTypeName<K> {
#[inline]
fn clone(&self) -> Self {
Self {
label: self.label.clone(),
_kind: PhantomData,
}
}
}
impl<K> PartialEq for ObjectTypeName<K> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.label == other.label
}
}
impl<K> Eq for ObjectTypeName<K> {}
impl<K> core::hash::Hash for ObjectTypeName<K> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.label.hash(state);
}
}
impl<K> core::fmt::Debug for ObjectTypeName<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("ObjectTypeName").field(&self.label).finish()
}
}
impl<K> core::fmt::Display for ObjectTypeName<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "ObjectTypeName(\"{}\")", self.label)
}
}
impl<K> PartialOrd for ObjectTypeName<K> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<K> Ord for ObjectTypeName<K> {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.label.cmp(&other.label)
}
}
pub struct EventTypeName<K> {
label: Cow<'static, str>,
_kind: PhantomData<K>,
}
impl<K> EventTypeName<K> {
#[inline]
pub fn from_static(label: &'static str) -> Self {
Self {
label: Cow::Borrowed(label),
_kind: PhantomData,
}
}
#[inline]
pub fn from_owned(label: String) -> Self {
Self {
label: Cow::Owned(label),
_kind: PhantomData,
}
}
#[inline]
pub fn as_str(&self) -> &str {
&self.label
}
}
impl<K> Clone for EventTypeName<K> {
#[inline]
fn clone(&self) -> Self {
Self {
label: self.label.clone(),
_kind: PhantomData,
}
}
}
impl<K> PartialEq for EventTypeName<K> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.label == other.label
}
}
impl<K> Eq for EventTypeName<K> {}
impl<K> core::hash::Hash for EventTypeName<K> {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.label.hash(state);
}
}
impl<K> core::fmt::Debug for EventTypeName<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("EventTypeName").field(&self.label).finish()
}
}
impl<K> core::fmt::Display for EventTypeName<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "EventTypeName(\"{}\")", self.label)
}
}
impl<K> PartialOrd for EventTypeName<K> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<K> Ord for EventTypeName<K> {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.label.cmp(&other.label)
}
}
pub fn id_of<T: NewFromRaw>(raw: T::Raw) -> T {
T::new_from_raw(raw)
}
pub trait NewFromRaw: sealed::SealedId {
type Raw;
fn new_from_raw(raw: Self::Raw) -> Self;
}
macro_rules! impl_new_from_raw {
($name:ident, $raw:ty) => {
impl<K> NewFromRaw for $name<K> {
type Raw = $raw;
#[inline]
fn new_from_raw(raw: $raw) -> Self {
Self::new(raw)
}
}
};
}
impl_new_from_raw!(EventId, u64);
impl_new_from_raw!(ObjectId, u64);
impl_new_from_raw!(ActivityId, u32);
impl_new_from_raw!(RelationId, u32);
impl_new_from_raw!(TraceId, u64);
impl_new_from_raw!(ObjectTypeId, u32);
impl_new_from_raw!(EventTypeId, u32);
impl_new_from_raw!(CaseId, u64);
macro_rules! impl_id_conversions {
($name:ident, $raw:ty) => {
impl<K> From<$raw> for $name<K> {
#[inline]
fn from(raw: $raw) -> Self {
Self::new(raw)
}
}
impl<K> From<$name<K>> for $raw {
#[inline]
fn from(id: $name<K>) -> $raw {
id.raw
}
}
impl<K> AsRef<$raw> for $name<K> {
#[inline]
fn as_ref(&self) -> &$raw {
&self.raw
}
}
impl<K> core::str::FromStr for $name<K> {
type Err = <$raw as core::str::FromStr>::Err;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<$raw>().map(Self::new)
}
}
};
}
impl_id_conversions!(EventId, u64);
impl_id_conversions!(ObjectId, u64);
impl_id_conversions!(ActivityId, u32);
impl_id_conversions!(RelationId, u32);
impl_id_conversions!(TraceId, u64);
impl_id_conversions!(ObjectTypeId, u32);
impl_id_conversions!(EventTypeId, u32);
impl_id_conversions!(CaseId, u64);
impl<K> From<&'static str> for ObjectTypeName<K> {
#[inline]
fn from(s: &'static str) -> Self {
Self::from_static(s)
}
}
impl<K> From<String> for ObjectTypeName<K> {
#[inline]
fn from(s: String) -> Self {
Self::from_owned(s)
}
}
impl<K> AsRef<str> for ObjectTypeName<K> {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<K> core::str::FromStr for ObjectTypeName<K> {
type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::from_owned(s.to_owned()))
}
}
impl<K> From<&'static str> for EventTypeName<K> {
#[inline]
fn from(s: &'static str) -> Self {
Self::from_static(s)
}
}
impl<K> From<String> for EventTypeName<K> {
#[inline]
fn from(s: String) -> Self {
Self::from_owned(s)
}
}
impl<K> AsRef<str> for EventTypeName<K> {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<K> core::str::FromStr for EventTypeName<K> {
type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::from_owned(s.to_owned()))
}
}