certain_map/
lib.rs

1// Copyright 2024 ihciah. All Rights Reserved.
2
3#![doc = include_str!("../README.md")]
4
5use std::mem::MaybeUninit;
6
7/// Re-export macro.
8pub use certain_map_macros::certain_map;
9/// Item of type T has been set in a certain_map slot.
10///
11/// When used as a trait bound, `Param<T>` ensures that the constrained type has previously
12/// used the [`ParamSet<T>`](trait.ParamSet.html) trait to set the value of type `T` in a
13/// `certain_map` slot. This allows the caller to guarantee at compile-time that the value of
14/// `T` is available and can be retrieved from the implementing type using the `param` method.
15///
16/// By using the `Param<T>` trait bound, you can enforce that the necessary value has been set
17/// before attempting to retrieve it, preventing runtime errors caused by missing or
18/// uninitialized values.
19///
20/// # Example
21///
22/// ```rust
23/// fn process_param<P: Param<T>, T>(param_provider: P) {
24///     let value: T = param_provider.param();
25///     // Use the value of type T
26/// }
27/// ```
28pub use param::Param;
29/// Item of type T may have been set in a certain_map slot and returns Option<&mut T>.
30///
31/// When used as a trait bound, `ParamMaybeMut<T>` ensures that the constrained type implements
32/// the `param_maybe_mut` method, which returns an `Option<&mut T>`. This allows the caller to
33/// attempt to retrieve a mutable reference to the value of type `T` from the implementing
34/// type, if it has been previously set in a `certain_map` slot using
35/// [`ParamSet<T>`](trait.ParamSet.html).
36///
37/// By using the `ParamMaybeMut<T>` trait bound, you can handle cases where the value may or
38/// may not have been set in the `certain_map`.
39///
40/// # Example
41///
42/// ```rust
43/// fn process_param_maybe_mut<P: ParamMaybeMut<T>, T>(param_provider: &mut P) {
44///     if let Some(value_mut) = param_provider.param_maybe_mut() {
45///         // Modify the value of type T
46///     }
47/// }
48/// ```
49pub use param::ParamMaybeMut;
50/// Item of type T may have been set in a certain_map slot and returns Option<&T>
51///
52/// When used as a trait bound, `ParamMaybeRef<T>` ensures that the constrained type implements
53/// the `param_maybe_ref` method, which returns an `Option<&T>`. This allows the caller to
54/// attempt to retrieve a reference to the value of type `T` from the implementing type, if it
55/// has been previously set in a `certain_map` slot using [`ParamSet<T>`](trait.ParamSet.html).
56///
57/// The `ParamMaybeRef<T>` trait does not guarantee that the value has been set in the
58/// `certain_map` slot. Instead, it returns an `Option<&T>`, which will be `Some(&T)` if the
59/// value has been set in the `certain_map` slot, and `None` if the value has not been set.
60///
61/// # Example
62///
63/// ```rust
64/// fn process_param_maybe_ref<P: ParamMaybeRef<T>, T>(param_provider: &P) {
65///     if let Some(value_ref) = param_provider.param_maybe_ref() {
66///         // Use the reference to the value of type T
67///     }
68/// }
69/// ```
70pub use param::ParamMaybeRef;
71/// Item of type T has been set in a certain_map slot and returns a mutable reference.
72///
73/// When used as a trait bound, `ParamMut<T>` ensures that the constrained type has previously
74/// used the [`ParamSet<T>`](trait.ParamSet.html) trait to set the value of type `T` in a
75/// `certain_map` slot. This allows the caller to guarantee at compile-time that the value of
76/// `T` is available and can be mutably accessed from the implementing type using the
77/// `param_mut` method.
78///
79/// # Example
80///
81/// ```rust
82/// fn process_param_mut<P: ParamMut<T>, T>(param_provider: &mut P) {
83///     let value_mut: &mut T = param_provider.param_mut();
84///     // Modify the value of type T
85/// }
86/// ```
87pub use param::ParamMut;
88/// Item of type T has been set in a certain_map slot and returns a reference.
89///
90/// When used as a trait bound, `ParamRef<T>` ensures that the constrained type implements the
91/// `param_ref` method, which returns a reference to the value of type `T`. This allows the
92/// caller to ensure that the value of `T` has been set in a `certain_map` slot and that a
93/// reference to it can be retrieved.
94///
95/// # Example
96///
97/// ```rust
98/// fn process_param_ref<P: ParamRef<T>, T>(param_provider: &P) {
99///     let value_ref: &T = param_provider.param_ref();
100///     // Use the reference to the value of type T
101/// }
102/// ```
103pub use param::ParamRef;
104/// Item of type T can be removed certain_map slot irrespective of it
105/// having been set before.
106pub use param::ParamRemove;
107/// Item of type T is vacant in certain_map slot.
108///
109/// The `ParamSet<T>` trait transforms the struct when a value is set. If the slot
110/// corresponding to the value of type `T` is currently of type [`Vacant`](struct.Vacant.html),
111/// setting a value using `param_set` will transform it to [`Occupied`](struct.Occupied.html),
112/// indicating that the value has been set. This transformation is reflected in the returned
113/// Transformed type.
114///
115/// By using the `ParamSet<T>` as a trait bound, you can ensure that you are not overwriting a
116/// field that has already been set. If you attempt to set a value in a slot that is already
117/// [`Occupied`](struct.Occupied.html), the Rust compiler will raise an error, preventing
118/// accidental overwrites and ensuring the integrity of the `certain_map` slots.
119pub use param::ParamSet;
120/// Item of type T has been set in certain_map slot and can be removed
121/// from the slot, leaving it vacant.
122pub use param::ParamTake;
123
124/// Represents an occupied slot in a certain_map slot.
125#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
126pub struct Occupied<T>(pub T);
127
128/// Represents an occupied slot in a certain_map slot.
129#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
130pub struct OccupiedM;
131
132/// Represents a vacant slot in a certain map.
133#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
134pub struct Vacancy;
135
136mod sealed {
137    pub trait Sealed {}
138    impl Sealed for super::OccupiedM {}
139    impl Sealed for super::Vacancy {}
140}
141
142pub trait MaybeAvailable: sealed::Sealed {
143    /// # Safety
144    /// Must called with correspond data reference.
145    unsafe fn do_maybe_ref<T>(data: &MaybeUninit<T>) -> Option<&T>;
146    /// # Safety
147    /// Must called with correspond data reference.
148    unsafe fn do_maybe_mut<T>(data: &mut MaybeUninit<T>) -> Option<&mut T>;
149    /// # Safety
150    /// Must called with correspond data reference and update state type.
151    unsafe fn do_set<T>(data: &mut MaybeUninit<T>, value: T);
152    /// # Safety
153    /// Must called with correspond data reference and update state type.
154    unsafe fn do_drop<T>(data: &mut MaybeUninit<T>);
155    /// # Safety
156    /// Must called with correspond data reference and update state type.
157    unsafe fn do_clone<T: Clone>(data: &MaybeUninit<T>) -> MaybeUninit<T>;
158    /// # Safety
159    /// Must called with correspond data reference.
160    unsafe fn do_debug<T: std::fmt::Debug>(
161        data: &MaybeUninit<T>,
162        f: &mut std::fmt::Formatter<'_>,
163    ) -> std::fmt::Result;
164}
165
166pub trait Available: MaybeAvailable {
167    /// # Safety
168    /// Must called with correspond data reference.
169    unsafe fn do_ref<T>(data: &MaybeUninit<T>) -> &T;
170    /// # Safety
171    /// Must called with correspond data reference.
172    unsafe fn do_mut<T>(data: &mut MaybeUninit<T>) -> &mut T;
173    /// # Safety
174    /// Must called with correspond data reference and update state type.
175    unsafe fn do_read<T: Clone>(data: &MaybeUninit<T>) -> T;
176    /// # Safety
177    /// Must called with correspond data reference and update state type.
178    unsafe fn do_take<T>(data: &MaybeUninit<T>) -> T;
179}
180
181impl Available for OccupiedM {
182    #[inline]
183    unsafe fn do_ref<T>(data: &MaybeUninit<T>) -> &T {
184        data.assume_init_ref()
185    }
186    #[inline]
187    unsafe fn do_mut<T>(data: &mut MaybeUninit<T>) -> &mut T {
188        data.assume_init_mut()
189    }
190    #[inline]
191    unsafe fn do_read<T: Clone>(data: &MaybeUninit<T>) -> T {
192        data.assume_init_ref().clone()
193    }
194    #[inline]
195    unsafe fn do_take<T>(data: &MaybeUninit<T>) -> T {
196        data.assume_init_read()
197    }
198}
199
200impl MaybeAvailable for OccupiedM {
201    #[inline]
202    unsafe fn do_maybe_ref<T>(data: &MaybeUninit<T>) -> Option<&T> {
203        Some(data.assume_init_ref())
204    }
205
206    #[inline]
207    unsafe fn do_maybe_mut<T>(data: &mut MaybeUninit<T>) -> Option<&mut T> {
208        Some(data.assume_init_mut())
209    }
210
211    #[inline]
212    unsafe fn do_set<T>(data: &mut MaybeUninit<T>, value: T) {
213        data.assume_init_drop();
214        *data = MaybeUninit::new(value)
215    }
216
217    #[inline]
218    unsafe fn do_drop<T>(data: &mut MaybeUninit<T>) {
219        data.assume_init_drop()
220    }
221
222    #[inline]
223    unsafe fn do_clone<T: Clone>(data: &MaybeUninit<T>) -> MaybeUninit<T> {
224        MaybeUninit::new(data.assume_init_ref().clone())
225    }
226
227    #[inline]
228    unsafe fn do_debug<T: std::fmt::Debug>(
229        data: &MaybeUninit<T>,
230        f: &mut std::fmt::Formatter<'_>,
231    ) -> std::fmt::Result {
232        write!(f, "Occupied: {:?}", data.assume_init_ref())
233    }
234}
235
236impl MaybeAvailable for Vacancy {
237    #[inline]
238    unsafe fn do_maybe_ref<T>(_data: &MaybeUninit<T>) -> Option<&T> {
239        None
240    }
241    #[inline]
242    unsafe fn do_maybe_mut<T>(_data: &mut MaybeUninit<T>) -> Option<&mut T> {
243        None
244    }
245    #[inline]
246    unsafe fn do_set<T>(data: &mut MaybeUninit<T>, value: T) {
247        *data = MaybeUninit::new(value)
248    }
249    #[inline]
250    unsafe fn do_drop<T>(_data: &mut MaybeUninit<T>) {}
251    #[inline]
252    unsafe fn do_clone<T: Clone>(_data: &MaybeUninit<T>) -> MaybeUninit<T> {
253        MaybeUninit::uninit()
254    }
255    #[inline]
256    unsafe fn do_debug<T: std::fmt::Debug>(
257        _data: &MaybeUninit<T>,
258        f: &mut std::fmt::Formatter<'_>,
259    ) -> std::fmt::Result {
260        write!(f, "Vacancy")
261    }
262}
263
264pub trait Handler {
265    type Hdr<'a>
266    where
267        Self: 'a;
268    fn handler(&mut self) -> Self::Hdr<'_>;
269}
270
271pub trait Fork {
272    type Store;
273    type State;
274    fn fork(&self) -> (Self::Store, Self::State);
275}
276
277pub trait Attach<Store> {
278    type Hdr<'a>
279    where
280        Store: 'a;
281    /// # Safety
282    /// The caller must make sure the attached map has the data of current state.
283    unsafe fn attach(self, store: &mut Store) -> Self::Hdr<'_>;
284}