abi_stable/sabi_types/
constructor.rs

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