variadic_arguments/argument/
arg.rs

1mod inner;
2
3#[cfg(no_std)]
4use core::{
5    any::Any,
6    fmt,
7    ops::Deref,
8    mem::ManuallyDrop
9};
10
11#[cfg(not(no_std))]
12use std::{
13    any::Any,
14    fmt,
15    ops::Deref,
16    mem::ManuallyDrop
17};
18
19use super::{OwnedArgument, discriminant::Discriminant};
20
21use inner::{RawArgument, InnerArgument};
22
23pub use inner::ArgumentKind;
24
25/// A variant item that implements Copy-on-Write.
26///
27/// It acts similarly to a [Cow], except for two things:
28/// 1. It is encapsulated, meaning that the inner contents cannot be accessed.
29/// 2. The storage is handled differently compared to [Cow], which allows for a smaller type size.
30///
31/// [Cow]: std::borrow::Cow
32#[repr(transparent)]
33pub struct Argument<'a>
34{
35    inner: InnerArgument<'a>
36}
37
38impl fmt::Debug for Argument<'_>
39{
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
41    {
42        match self.inner.discriminant()
43        {
44            Discriminant::Borrowed =>
45            {
46                f.debug_tuple("Argument::Borrowed")
47                 .field(&self.inner.to_ref())
48                 .finish()
49            }
50            _ =>
51            {
52                f.debug_tuple("Argument::Owned")
53                 .field(unsafe { self.inner.owned_debug_handle() })
54                 .finish()
55            }
56        }
57    }
58}
59
60impl Drop for Argument<'_>
61{
62    fn drop(&mut self)
63    {
64        let _ = unsafe { self.inner.as_argument() };
65    }
66}
67
68impl<'a> Clone for Argument<'a>
69{
70    fn clone(&self) -> Self
71    {
72        let inner =
73        match self.inner.discriminant()
74        {
75            Discriminant::Borrowed =>
76            {
77                let ref_ = unsafe { self.inner.inner_ref() };
78                
79                InnerArgument::new_ref(ref_)
80            }
81            _ =>
82            {
83                let owned =
84                {
85                    let raw = &raw const self.inner;
86                    unsafe
87                    {
88                        (*raw.cast::<OwnedArgument>()).clone()
89                    }
90                };
91                
92                InnerArgument::new_owned(owned)
93            }
94        };
95        
96        Self
97        {
98            inner
99        }
100    }
101}
102
103impl Deref for Argument<'_>
104{
105    type Target = dyn Any;
106    
107    fn deref(&self) -> &dyn Any
108    {
109        self.inner.to_ref()
110    }
111}
112
113impl Argument<'_>
114{
115    /// Creates a new owned Argument.
116    pub fn new_owned<T>(item: T) -> Self
117    where
118        T: Any + Clone
119    {
120        let owned = OwnedArgument::new(item);
121        
122        Self
123        {
124            inner: InnerArgument::new_owned(owned)
125        }
126    }
127    
128    /// Checks if the argument is owned.
129    pub fn is_owned(&self) -> bool
130    {
131        self.inner
132            .is_owned()
133    }
134    
135    /// Checks if the argument is borrowed.
136    pub fn is_borrowed(&self) -> bool
137    {
138        self.inner
139            .is_borrowed()
140    }
141    
142    /// Returns a mutable reference to the item itself.
143    ///
144    /// If the inner contents are borrowed, this creates a new
145    /// owned instance first before returning the reference itself.
146    pub fn to_mut(&mut self) -> &mut dyn Any
147    {
148        self.inner.to_mut()
149    }
150    
151    /// Clones the inner contents of the object, returning an owned argument.
152    pub fn to_owned(&self) -> Self
153    {
154        match self.inner.discriminant()
155        {
156            Discriminant::Borrowed =>
157            {
158                let ref_ = unsafe { self.inner.inner_ref() };
159                
160                let owned = ref_.clone_object();
161                
162                Self
163                {
164                    inner: InnerArgument::new_owned(owned)
165                }
166            }
167            _ => self.clone()
168        }
169    }
170    
171    /// Downcasts an owned argument into type T, returning a result.
172    ///
173    /// # Return values
174    /// Ok(T): The argument gets consumed and returns the inner contents.
175    /// Err(Self): Either the argument is not of type T or the argument itself is not owned.
176    pub fn downcast_owned<T>(self) -> Result<T, Self>
177    where
178        T: Clone + Any
179    {
180        match self.inner_contents()
181        {
182            RawArgument::Owned(o)
183            if o.is_type::<T>()
184            => unsafe { Ok(o.downcast_owned_unchecked() ) }
185            
186            RawArgument::Owned(o)
187            =>
188            Err(Self { inner: InnerArgument::new_owned(o) }),
189            
190            RawArgument::Borrowed(b)
191            =>
192            Err(Self { inner: InnerArgument::new_ref(b) })
193        }
194    }
195    
196    /// Downcasts an owned argument into type T, without any checks.
197    ///
198    /// # Safety
199    /// The argument must both be owned and of type T.
200    ///
201    /// # Panics
202    /// The function will panic if the argument itself is not owned.
203    pub unsafe fn downcast_owned_unchecked<T>(self) -> T
204    where
205        T: Clone + Any
206    {
207        debug_assert!(self.is_owned());
208        
209        let RawArgument::Owned(contents) = self.inner_contents()
210        else
211        {
212            #[cfg(debug_assertions)]
213            {
214                unreachable!()
215            }
216            #[cfg(not(debug_assertions))]
217            {
218                panic!()
219            }
220        };
221        
222        debug_assert!(contents.is_type::<T>());
223        
224        unsafe
225        {
226            contents.downcast_owned_unchecked()
227        }
228    }
229    
230    /// Downcasts the argument into a cloned object of type T.
231    ///
232    /// Returns None if the object's type is not T.
233    pub fn downcast_cloned<T>(&self) -> Option<T>
234    where
235        T: Any + Clone
236    {
237        #[allow(clippy::manual_map)]
238        match self.downcast_ref::<T>()
239        {
240            Some(t) => Some(t.clone()),
241            None => None
242        }
243    }
244    
245    /// Binding to downcast a reference to T without checks.
246    ///
247    /// This is similar to Any::downcast_ref_unchecked, except for
248    /// the fact that we can use it outside of nightly. When the former
249    /// gets stabilized, this function will get replaced.
250    ///
251    /// # Safety
252    /// Assumes that the contents are of type T.
253    unsafe fn downcast_ref_unchecked<T>(&self) -> &T
254    where
255        T: Any + Clone
256    {
257        let binding = self.inner.to_ref();
258        
259        debug_assert!(binding.is::<T>());
260        
261        unsafe
262        {
263            &*(binding as *const dyn Any as *const T)
264        }
265    }
266    
267    /// Downcasts the argument into a cloned object of T without checking it first.
268    ///
269    /// # Safety
270    /// Assumes that the contents are of type T.
271    pub unsafe fn downcast_cloned_unchecked<T>(&self) -> T
272    where
273        T: Any + Clone
274    {
275        unsafe
276        {
277            self.downcast_ref_unchecked::<T>().clone()
278        }
279    }
280}
281
282impl<'a> Argument<'a>
283{
284    /// Creates a borrowed argument of item T.
285    pub fn new_borrowed<T>(item: &'a T) -> Self
286    where
287        T: Any + Clone
288    {
289        Self
290        {
291            inner: InnerArgument::new_ref(item)
292        }
293    }
294    
295    /// Creates a borrowed reference to the source argument.
296    pub fn as_ref(&'a self) -> Self
297    {
298        Self
299        {
300            inner: self.inner.as_ref()
301        }
302    }
303    
304    /// Consumes the argument, returning a wrapper to the inner argument itself.
305    fn inner_contents(self) -> RawArgument<'a>
306    {
307        let mut store = ManuallyDrop::new(self);
308        
309        unsafe
310        {
311            store.inner.as_argument()
312        }
313    }
314    
315    /// Consumes the argument itself, returning what kind of argument it is.
316    pub fn into_inner(self) -> ArgumentKind<'a>
317    {
318        let store = ManuallyDrop::new(self);
319        
320        let raw = &raw const store.inner;
321        
322        unsafe
323        {
324            raw.read().into_inner()
325        }
326    }
327}