variadic_arguments/argument/
arg.rs1mod 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#[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 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 pub fn is_owned(&self) -> bool
130 {
131 self.inner
132 .is_owned()
133 }
134
135 pub fn is_borrowed(&self) -> bool
137 {
138 self.inner
139 .is_borrowed()
140 }
141
142 pub fn to_mut(&mut self) -> &mut dyn Any
147 {
148 self.inner.to_mut()
149 }
150
151 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 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 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 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 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 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 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 pub fn as_ref(&'a self) -> Self
297 {
298 Self
299 {
300 inner: self.inner.as_ref()
301 }
302 }
303
304 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 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}