1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
use std::{
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
fmt::{self, Debug, Display},
};
/// Newtype wrapper to pass function pointers to `const fn`.
///
/// A workaround for it not being possible to get a function pointer within a `const fn`,
/// since it's possible to pass structs that happen to have function pointer fields.
///
/// Every impl of this type delegates the impl to the return value of the wrapped function
/// (which it calls every time),don't use those impls if the function is likely expensive.
///
/// # Example
///
/// ```
/// use abi_stable::{
/// sabi_types::Constructor,
/// std_types::{RNone, ROption, RSome},
/// };
///
/// extern "C" fn returns_100() -> ROption<u32> {
/// RSome(100)
/// }
///
/// extern "C" fn returns_100b() -> ROption<u32> {
/// RSome(100)
/// }
///
/// extern "C" fn returns_200() -> ROption<u32> {
/// RSome(200)
/// }
///
/// extern "C" fn returns_none() -> ROption<u32> {
/// RNone
/// }
///
/// const A: Constructor<ROption<u32>> = Constructor(returns_100);
/// const B: Constructor<ROption<u32>> = Constructor(returns_100b);
/// const C: Constructor<ROption<u32>> = Constructor(returns_200);
/// const D: Constructor<ROption<u32>> = Constructor(returns_none);
///
/// assert_eq!(A, A);
/// assert_eq!(B, B);
/// assert_eq!(C, C);
/// assert_eq!(D, D);
///
/// assert_eq!(A, B);
///
/// assert_ne!(A, C);
/// assert_ne!(A, D);
/// assert_ne!(B, C);
/// assert_ne!(C, D);
///
/// ```
///
#[repr(transparent)]
#[derive(StableAbi)]
// #[sabi(debug_print)]
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> {
/// Constructs a `T` by calling the wrapped function.
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())
}
}
////////////////////////////////////////////////////////////////////////////////
/// Either the constructor for a value or the value itself
#[repr(u8)]
#[derive(StableAbi, Copy, Clone)]
//#[sabi(debug_print)]
pub enum ConstructorOrValue<T> {
/// This is an `extern "C" fn()->T` which is used to construct a value of type `T`
Constructor(Constructor<T>),
/// A value of type `T`
Value(T),
}
impl<T> ConstructorOrValue<T> {
/// Gets the wrapped value,computing it from its constructor if this
/// is the `Constructor` variant
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!(),
}
}
}
}
}