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}