enum_ptr/utils/
get.rs

1use crate::{Compact, Compactable, FieldDeref, FieldDerefMut};
2
3#[doc(hidden)]
4#[inline]
5pub unsafe fn get_ref_helper<T, U>(
6    compact: &Compact<T>,
7    f: impl FnOnce(&T) -> Option<&U>,
8) -> Option<<U as FieldDeref>::Target<'_>>
9where
10    T: Compactable,
11    U: FieldDeref,
12{
13    compact.map_ref(|tmp| f(tmp).map(|tmp| tmp.force_deref()))
14}
15
16#[doc(hidden)]
17#[inline]
18pub unsafe fn get_mut_helper<T, U>(
19    compact: &mut Compact<T>,
20    f: impl FnOnce(&mut T) -> Option<&mut U>,
21) -> Option<<U as FieldDerefMut>::Target<'_>>
22where
23    T: Compactable,
24    U: FieldDerefMut,
25{
26    compact.map_mut(|tmp| f(tmp).map(|tmp| tmp.force_deref_mut()))
27}
28
29/// Borrows a variant from [`Compact`].
30///
31/// It requires the type of that variant implements [`FieldDeref`].
32///
33/// # Examples
34///
35/// ```
36/// # #[cfg(feature = "alloc")] {
37/// use enum_ptr::{get_ref, Compact, EnumPtr};
38///
39/// #[derive(EnumPtr)]
40/// #[repr(C, usize)]
41/// enum Foo {
42///     A(Box<i32>),
43///     B(Box<u32>),
44/// }
45///
46/// let foo: Compact<_> = Foo::A(Box::new(1)).into();
47/// assert_eq!(get_ref!(foo, Foo::A), Some(&1));
48/// assert_eq!(get_ref!(foo, Foo::B), None);
49/// # }
50/// ```
51#[macro_export]
52macro_rules! get_ref {
53    ($compact:expr, $variant:path) => {
54        unsafe {
55            $crate::get_ref_helper(&$compact, |tmp| match tmp {
56                $variant(inner) => Some(inner),
57                _ => None,
58            })
59        }
60    };
61}
62
63/// Mutably borrows a variant from [`Compact`].
64///
65/// It requires the type of that variant implements [`FieldDerefMut`].
66///
67/// # Examples
68///
69/// ```
70/// # #[cfg(feature = "alloc")] {
71/// use enum_ptr::{get_mut, Compact, EnumPtr};
72///
73/// #[derive(EnumPtr)]
74/// #[repr(C, usize)]
75/// enum Foo {
76///     A(Box<i32>),
77///     B(Box<u32>),
78/// }
79///
80/// let mut foo: Compact<_> = Foo::A(Box::new(1)).into();
81/// assert_eq!(get_mut!(foo, Foo::A), Some(&mut 1));
82/// assert_eq!(get_mut!(foo, Foo::B), None);
83/// # }
84/// ```
85#[macro_export]
86macro_rules! get_mut {
87    ($compact:expr, $variant:path) => {
88        unsafe {
89            $crate::get_mut_helper(&mut $compact, |tmp| match tmp {
90                $variant(inner) => Some(inner),
91                _ => None,
92            })
93        }
94    };
95}