iob/
lib.rs

1#![no_std]
2
3use core::{
4    marker::PhantomData,
5    mem::MaybeUninit,
6    ops::{Deref, DerefMut},
7};
8pub struct In<'a, T> {
9    pub ptr: *mut T,
10    _private: PhantomData<&'a ()>,
11}
12pub struct Out<'a, T> {
13    pub ptr: *mut T,
14    _private: PhantomData<&'a ()>,
15}
16impl<'a, T> In<'a, T> {
17    pub fn fill(self, value: T) -> Out<'a, T> {
18        unsafe {
19            self.ptr.write(value);
20        }
21        Out {
22            ptr: self.ptr,
23            _private: self._private,
24        }
25    }
26    pub unsafe fn raw<F>(raw: *mut T, f: F) -> Out<'a, T>
27    where
28        F: FnOnce(In<T>) -> Out<T>,
29    {
30        f(In {
31            ptr: raw,
32            _private: PhantomData,
33        })
34    }
35}
36impl<'a, T> Deref for Out<'a, T> {
37    type Target = T;
38
39    fn deref(&self) -> &Self::Target {
40        unsafe { &*self.ptr }
41    }
42}
43impl<'a, T> DerefMut for Out<'a, T> {
44    fn deref_mut(&mut self) -> &mut Self::Target {
45        unsafe { &mut *self.ptr }
46    }
47}
48impl<'a, T> Out<'a, T> {
49    pub unsafe fn from_raw(a: *mut T) -> Self {
50        Self {
51            ptr: a,
52            _private: PhantomData,
53        }
54    }
55}
56pub fn stack<T, E>(
57    f: impl for<'a> FnOnce(In<'a, T>) -> Result<Out<'a, T>, (In<'a, T>, E)>,
58) -> Result<T, E> {
59    let mut x = MaybeUninit::uninit();
60    match f(In {
61        ptr: x.as_mut_ptr(),
62        _private: PhantomData,
63    }) {
64        Err((_, e)) => return Err(e),
65        Ok(o) => {
66            return Ok(unsafe { o.ptr.read() });
67        }
68    }
69}
70#[macro_export]
71macro_rules! init {
72    ($p:ident.$field:ident @ $then:expr) => {
73        $crate::In::raw(
74            $crate::__::core::ptr::addr_of_mut!((*$p).$field),
75            move |$p| $then,
76        )
77    };
78    ($p:ident.$field:ident = $val:expr) => {
79        $crate::In::raw($crate::__::core::ptr::addr_of_mut!((*$p).$field), |$p| {
80            $p.fill($val)
81        })
82    };
83}
84#[doc(hidden)]
85pub mod __ {
86    pub use core;
87}