variadic_arguments/argument/arg/
inner.rs

1#[cfg(no_std)]
2use core::{
3    any::Any,
4    fmt::Debug,
5    mem::{ManuallyDrop, MaybeUninit},
6};
7
8use crate::{argument::VariantHandle,argument::discriminant::Discriminant, OwnedArgument};
9
10#[cfg(not(no_std))]
11use std::{
12    any::Any,
13    fmt::Debug,
14    mem::{ManuallyDrop, MaybeUninit}
15};
16
17/// The argument kind returned from Argument::into_inner.
18#[derive(Debug)]
19pub enum ArgumentKind<'a>
20{
21    /// The inner contents are borrowed.
22    Borrowed(&'a dyn Any),
23    /// The inner contents are owned.
24    Owned(OwnedArgument)
25}
26
27pub(super) enum RawArgument<'a>
28{
29    Borrowed(&'a dyn VariantHandle),
30    Owned(OwnedArgument)
31}
32
33/// A union structure aimed at managing a more compact CoW instance.
34pub(super) union InnerArgument<'a>
35{
36    /// This points to owned storage. Even if it is not initialized, it still
37    /// points to valuable data, such as determining the argument's current state.
38    owned: ManuallyDrop<OwnedArgument>,
39    /// This pointer, if written, will only overwrite the main, owned storage. It should
40    /// not overwrite the essential information, such as owned/inlined status.
41    ref_: &'a dyn VariantHandle
42}
43
44impl InnerArgument<'_>
45{
46    /// Creates a new owned argument.
47    #[inline(always)]
48    pub fn new_owned(item: OwnedArgument) -> Self
49    {
50        let owned = ManuallyDrop::new(item);
51        
52        Self
53        {
54            owned
55        }
56    }
57    
58    
59    /// Provides the discriminant for the inner storage.
60    #[inline(always)]
61    pub fn discriminant(&self) -> Discriminant
62    {
63        // Safety: We are only accessing discriminant information.
64        unsafe
65        {
66            self.owned
67                .discriminant()
68        }
69    }
70    
71    
72    #[inline(always)]
73    pub fn is_owned(&self) -> bool
74    {
75        matches!(self.discriminant(), Discriminant::Inlined | Discriminant::Allocated )
76    }
77    
78    
79    #[inline(always)]
80    pub fn is_borrowed(&self) -> bool
81    {
82        matches!(self.discriminant(), Discriminant::Borrowed)
83    }
84    
85    
86    #[inline(always)]
87    pub fn to_mut(&mut self) -> &mut dyn Any
88    {
89        match self.discriminant()
90        {
91            Discriminant::Borrowed =>
92            {
93                let owned : OwnedArgument = 
94                unsafe
95                {
96                    self.ref_.clone_object()
97                };
98                
99                *self = InnerArgument::new_owned(owned);
100                
101                match self.discriminant()
102                {
103                    Discriminant::Inlined | Discriminant::Allocated =>
104                    unsafe
105                    {
106                        &mut *self.owned
107                    },
108                    _ => unreachable!()
109                }
110            }
111            _ =>
112            unsafe
113            {
114                &mut *self.owned
115            }
116        }
117    }
118    
119    
120    /// Provides a debug handle to an owned pointer.
121    ///
122    /// # Safety
123    /// The inner contents must be owned.
124    #[inline(always)]
125    pub unsafe fn owned_debug_handle(&self) -> &dyn Debug
126    {
127        unsafe
128        {
129            &*self.owned
130        }
131    }
132}
133
134
135impl<'a> InnerArgument<'a>
136{
137    /// Creates a new instance from a borrowed trait handle.
138    #[inline(always)]
139    pub fn new_ref(ref_: &'a dyn VariantHandle) -> Self
140    {
141        // Safety: This lets us "initialize" a borrowed instance.
142        let mut output : Self = unsafe { MaybeUninit::zeroed().assume_init() };
143        
144        output.ref_ = ref_;
145        
146        output
147    }
148    
149    /// Creates a new object based around a reference to the source object.
150    #[inline(always)]
151    pub fn as_ref(&'a self) -> Self
152    {
153        let ref_ =
154        match self.discriminant()
155        {
156            Discriminant::Borrowed => unsafe { self.ref_unchecked() },
157            _ => unsafe { self.owned.raw_ref() }
158        };
159        
160        Self::new_ref(ref_)
161    }
162    
163    /// Takes the inner contents of the storage itself.
164    ///
165    /// # Safety
166    /// This assumes that not only the result must be used,
167    /// but the function should be called once.
168    #[must_use = "Potential memory leak."]
169    #[inline(always)]
170    pub unsafe fn take_raw_argument(&mut self) -> RawArgument<'a>
171    {
172        match self.discriminant()
173        {
174            Discriminant::Borrowed =>
175            {
176                let ref_ = unsafe { self.ref_unchecked() };
177                
178                RawArgument::Borrowed(ref_)
179            }
180            _ =>
181            {
182                let owned =
183                unsafe
184                {
185                    ManuallyDrop::take(&mut self.owned)
186                };
187                
188                RawArgument::Owned(owned)
189            }
190        }
191    }
192    
193    
194    #[inline(always)]
195    pub fn into_inner(self) -> ArgumentKind<'a>
196    {
197        match self.discriminant()
198        {
199            Discriminant::Borrowed => ArgumentKind::Borrowed(unsafe { self.ref_unchecked() }),
200            _ => ArgumentKind::Owned(ManuallyDrop::into_inner(unsafe { self.owned }))
201        }
202    }
203    
204    
205    /// Acquires the inner reference to the object's reference.
206    ///
207    /// # Safety
208    /// This assumes that the storage itself is borrowed.
209    #[inline(always)]
210    pub unsafe fn ref_unchecked(&self) -> &'a dyn VariantHandle
211    {
212        unsafe
213        {
214            self.ref_
215        }
216    }
217    
218    
219    #[inline(always)]
220    pub fn to_ref(&'a self) -> &'a dyn Any
221    {
222        match self.discriminant()
223        {
224            Discriminant::Borrowed => unsafe { self.ref_unchecked() },
225            _ => unsafe { self.owned.raw_ref() }
226        }
227    }
228}