use std::{
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
fmt::{self, Debug, Display},
};
#[repr(transparent)]
#[derive(StableAbi)]
pub struct Constructor<T>(pub extern "C" fn() -> T);
impl<T> Copy for Constructor<T> {}
impl<T> Clone for Constructor<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Debug for Constructor<T>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.get(), f)
}
}
impl<T> Display for Constructor<T>
where
T: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.get(), f)
}
}
impl<T> Constructor<T> {
pub fn get(self) -> T {
(self.0)()
}
pub(crate) const fn wrap_slice(slice: &[extern "C" fn() -> T]) -> &[Constructor<T>] {
unsafe { &*(slice as *const [extern "C" fn() -> T] as *const [Constructor<T>]) }
}
pub(crate) const fn unwrap_slice(slice: &[Constructor<T>]) -> &[extern "C" fn() -> T] {
unsafe { &*(slice as *const [Constructor<T>] as *const [extern "C" fn() -> T]) }
}
}
impl<T> Eq for Constructor<T> where T: Eq {}
impl<T> PartialEq for Constructor<T>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<T> Ord for Constructor<T>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
self.get().cmp(&other.get())
}
}
impl<T> PartialOrd for Constructor<T>
where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.get().partial_cmp(&other.get())
}
}
#[repr(u8)]
#[derive(StableAbi, Copy, Clone)]
pub enum ConstructorOrValue<T> {
Constructor(Constructor<T>),
Value(T),
}
impl<T> ConstructorOrValue<T> {
pub fn get(&mut self) -> &T {
match self {
ConstructorOrValue::Value(v) => v,
&mut ConstructorOrValue::Constructor(func) => {
let v = (func.0)();
*self = ConstructorOrValue::Value(v);
match self {
ConstructorOrValue::Value(v) => v,
_ => unreachable!(),
}
}
}
}
}