dync/
value.rs

1//! This module defines a mechanism for type earasure simplar to `dyn Any`.
2//!
3//! This method allows storing and referencing values coming from a `VecDrop` inside other `std`
4//! containers without needing a downcast.
5//!
6#![allow(dead_code)]
7
8use std::any::{Any, TypeId};
9use std::fmt;
10use std::hash::{Hash, Hasher};
11use std::mem::{ManuallyDrop, MaybeUninit};
12
13// At the time of this writing, there is no evidence that there is a significant benefit in sharing
14// vtables via Rc or Arc, but to make potential future refactoring easier we use the Ptr alias.
15use std::boxed::Box as Ptr;
16
17use crate::bytes::*;
18pub use crate::copy_value::*;
19use crate::traits::*;
20use crate::vtable::*;
21
22#[derive(Debug)]
23pub enum Error {
24    /// Value could not fit into a single pointer sized word.
25    ValueTooLarge,
26    /// Mismatched types.
27    ///
28    /// Trying to assign a value of one type to a value of another.
29    MismatchedTypes { expected: TypeId, actual: TypeId },
30}
31
32impl fmt::Display for Error {
33    #[inline]
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        match self {
36            Error::ValueTooLarge => {
37                write!(f, "Value could not fit into a single pointer sized word.\nTry constructing a BoxValue instead.")?;
38            }
39            Error::MismatchedTypes { expected, actual } => {
40                writeln!(f, "Trying to assign a value of one type (with TypeId {:?}) to a value of another (with TypeId {:?}).", actual, expected)?;
41            }
42        }
43        Ok(())
44    }
45}
46
47impl std::error::Error for Error {}
48
49impl<T: Any> HasDrop for (DropFn, T) {
50    #[inline]
51    fn drop_fn(&self) -> &DropFn {
52        &self.0
53    }
54}
55
56// The following forwarding impls make it more straightforward to call the Has* methods on the
57// (DropFn, V) vtable, although they are not strictly necessary.
58
59impl<V: HasClone> HasClone for (DropFn, V) {
60    #[inline]
61    fn clone_fn(&self) -> &CloneFn {
62        self.1.clone_fn()
63    }
64    #[inline]
65    fn clone_from_fn(&self) -> &CloneFromFn {
66        self.1.clone_from_fn()
67    }
68    #[inline]
69    fn clone_into_raw_fn(&self) -> &CloneIntoRawFn {
70        self.1.clone_into_raw_fn()
71    }
72}
73
74impl<V: HasHash> HasHash for (DropFn, V) {
75    #[inline]
76    fn hash_fn(&self) -> &HashFn {
77        self.1.hash_fn()
78    }
79}
80
81impl<V: HasPartialEq> HasPartialEq for (DropFn, V) {
82    #[inline]
83    fn eq_fn(&self) -> &EqFn {
84        self.1.eq_fn()
85    }
86}
87
88impl<V: HasEq> HasEq for (DropFn, V) {}
89
90impl<V: HasDebug> HasDebug for (DropFn, V) {
91    #[inline]
92    fn fmt_fn(&self) -> &FmtFn {
93        self.1.fmt_fn()
94    }
95}
96
97pub struct Value<B, V>
98where
99    B: GetBytesMut + DropAsAligned,
100    V: ?Sized + HasDrop,
101{
102    pub(crate) bytes: ManuallyDrop<B>,
103    pub(crate) type_id: TypeId,
104    pub(crate) alignment: usize,
105    pub(crate) vtable: ManuallyDrop<Ptr<V>>,
106}
107
108pub type SmallValue<V> = Value<MaybeUninit<usize>, V>;
109pub type BoxValue<V> = Value<Box<[MaybeUninit<u8>]>, V>;
110
111impl<V: HasDrop> SmallValue<V> {
112    #[inline]
113    pub fn try_new<T: Any + DropBytes>(value: T) -> Option<Value<MaybeUninit<usize>, V>>
114    where
115        V: VTable<T>,
116    {
117        // Prevent drop of value when it goes out of scope.
118        let val = ManuallyDrop::new(value);
119        val.try_into_usize().map(|usized_value| Value {
120            bytes: ManuallyDrop::new(usized_value),
121            type_id: TypeId::of::<T>(),
122            alignment: std::mem::align_of::<T>(),
123            vtable: ManuallyDrop::new(Ptr::new(V::build_vtable())),
124        })
125    }
126    /// This function will panic if the given type does not fit into a `usize`.
127    #[inline]
128    pub fn new<T: Any + DropBytes>(value: T) -> Value<MaybeUninit<usize>, V>
129    where
130        V: VTable<T>,
131    {
132        Self::try_new(value).unwrap()
133    }
134}
135
136impl<V: ?Sized + HasDrop> SmallValue<V> {
137    /// Create a new `SmallValue` from a `usize` and an associated `TypeId`.
138    ///
139    /// # Safety
140    ///
141    /// The given bytes must be the correct representation of the type given `TypeId`.
142    #[inline]
143    pub(crate) unsafe fn from_raw_parts(
144        bytes: MaybeUninit<usize>,
145        type_id: TypeId,
146        alignment: usize,
147        vtable: Ptr<V>,
148    ) -> Value<MaybeUninit<usize>, V> {
149        Value {
150            bytes: ManuallyDrop::new(bytes),
151            type_id,
152            alignment,
153            vtable: ManuallyDrop::new(vtable),
154        }
155    }
156
157    #[inline]
158    pub fn upcast<U: HasDrop + From<V>>(self) -> SmallValue<U>
159    where
160        V: Clone,
161    {
162        // Inhibit drop for self, it will be dropped by the returned value
163        let mut md = ManuallyDrop::new(self);
164        let output = Value {
165            bytes: md.bytes,
166            type_id: md.type_id,
167            alignment: md.alignment,
168            vtable: ManuallyDrop::new(Ptr::new(U::from((**md.vtable).clone()))),
169        };
170
171        // Manually drop the old vtable.
172        // This is safe since the old vtable will not be used again since self is consumed.
173        // It will also not be double dropped since it is cloned above.
174        unsafe {
175            ManuallyDrop::drop(&mut md.vtable);
176        }
177
178        output
179    }
180
181    /// Convert this value into its destructured parts.
182    ///
183    /// The caller must insure that the memory allocated by the returned bytes is freed.
184    #[inline]
185    pub fn into_raw_parts(self) -> (MaybeUninit<usize>, TypeId, usize, Ptr<V>) {
186        // Inhibit drop for self.
187        let mut md = ManuallyDrop::new(self);
188
189        // Pass ownership of the vtable and bytes to the caller. This allows the table to be
190        // dropped automatically if the caller ignores it, however the data represented by bytes
191        // is leaked.
192        let vtable = unsafe { ManuallyDrop::take(&mut md.vtable) };
193        let bytes = unsafe { ManuallyDrop::take(&mut md.bytes) };
194
195        (bytes, md.type_id, md.alignment, vtable)
196    }
197}
198
199impl<V: HasDrop> BoxValue<V> {
200    #[inline]
201    pub fn new<T: Any + DropBytes>(value: T) -> Value<Box<[MaybeUninit<u8>]>, V>
202    where
203        V: VTable<T>,
204    {
205        Value {
206            bytes: ManuallyDrop::new(Bytes::box_into_box_bytes(Box::new(value))),
207            type_id: TypeId::of::<T>(),
208            alignment: std::mem::align_of::<T>(),
209            vtable: ManuallyDrop::new(Ptr::new(V::build_vtable())),
210        }
211    }
212}
213
214impl<V: ?Sized + HasDrop> BoxValue<V> {
215    /// Create a new `BoxValue` from boxed bytes and an associated `TypeId`.
216    ///
217    /// # Safety
218    ///
219    /// The given bytes must be the correct representation of the type given `TypeId`.
220    #[inline]
221    pub(crate) unsafe fn from_raw_parts(
222        bytes: Box<[MaybeUninit<u8>]>,
223        type_id: TypeId,
224        alignment: usize,
225        vtable: Ptr<V>,
226    ) -> Value<Box<[MaybeUninit<u8>]>, V> {
227        Value {
228            bytes: ManuallyDrop::new(bytes),
229            type_id,
230            alignment,
231            vtable: ManuallyDrop::new(vtable),
232        }
233    }
234
235    #[inline]
236    pub fn upcast<U: HasDrop + From<V>>(self) -> BoxValue<U>
237    where
238        V: Clone,
239    {
240        // Inhibit drop for self, it will be dropped by the returned value
241        let mut md = ManuallyDrop::new(self);
242        // It is safe to take the bytes from md since self is consumed and will not be used later.
243        let output = Value {
244            bytes: ManuallyDrop::new(unsafe { ManuallyDrop::take(&mut md.bytes) }),
245            type_id: md.type_id,
246            alignment: md.alignment,
247            vtable: ManuallyDrop::new(Ptr::new(U::from((**md.vtable).clone()))),
248        };
249
250        // Manually drop the old vtable.
251        // This is safe since the old vtable will not be used again since self is consumed.
252        // It will also not be double dropped since it is cloned above.
253        unsafe {
254            ManuallyDrop::drop(&mut md.vtable);
255        }
256
257        output
258    }
259
260    /// Convert this value into its destructured parts.
261    ///
262    /// The caller must insure that the memory allocated by the returned bytes is freed.
263    #[inline]
264    pub fn into_raw_parts(self) -> (Box<[MaybeUninit<u8>]>, TypeId, usize, Ptr<V>) {
265        // Inhibit drop for self.
266        let mut md = ManuallyDrop::new(self);
267
268        // Pass ownership of the vtable and bytes to the caller. This allows the table to be
269        // dropped automatically if the caller ignores it, however the data represented by bytes
270        // is leaked.
271        let vtable = unsafe { ManuallyDrop::take(&mut md.vtable) };
272        let bytes = unsafe { ManuallyDrop::take(&mut md.bytes) };
273
274        (bytes, md.type_id, md.alignment, vtable)
275    }
276}
277
278impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop> Value<B, V> {
279    #[inline]
280    pub fn as_ref(&self) -> ValueRef<V> {
281        ValueRef {
282            bytes: self.bytes.get_bytes_ref(),
283            type_id: self.type_id,
284            alignment: self.alignment,
285            vtable: VTableRef::Ref(&self.vtable),
286        }
287    }
288    #[inline]
289    pub fn as_mut(&mut self) -> ValueMut<V> {
290        ValueMut {
291            bytes: self.bytes.get_bytes_mut(),
292            type_id: self.type_id,
293            alignment: self.alignment,
294            vtable: VTableRef::Ref(&self.vtable),
295        }
296    }
297}
298
299unsafe impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop + HasSend> Send for Value<B, V> {}
300unsafe impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop + HasSync> Sync for Value<B, V> {}
301
302impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDebug + HasDrop> fmt::Debug for Value<B, V> {
303    #[inline]
304    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
305        unsafe { self.vtable.fmt_fn()(self.bytes.get_bytes_ref(), f) }
306    }
307}
308
309impl<V: ?Sized + Clone + HasClone + HasDrop> Clone for Value<MaybeUninit<usize>, V> {
310    #[inline]
311    fn clone(&self) -> Value<MaybeUninit<usize>, V> {
312        self.as_ref().clone_small_value()
313    }
314}
315
316impl<V: ?Sized + Clone + HasClone + HasDrop> Clone for Value<Box<[MaybeUninit<u8>]>, V> {
317    #[inline]
318    fn clone(&self) -> Value<Box<[MaybeUninit<u8>]>, V> {
319        self.as_ref().clone_value()
320    }
321}
322
323impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop> Drop for Value<B, V> {
324    #[inline]
325    fn drop(&mut self) {
326        unsafe {
327            // SAFETY: Self will never be used after this call.
328            self.vtable.drop_fn()(self.bytes.get_bytes_mut());
329
330            // Manually drop what we promised.
331            self.bytes.drop_as_aligned(self.alignment);
332            ManuallyDrop::drop(&mut self.vtable);
333        }
334    }
335}
336
337impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop + HasPartialEq> PartialEq for Value<B, V> {
338    /// # Panics
339    ///
340    /// This function panics if the types of the two operands don't match.
341    #[inline]
342    fn eq(&self, other: &Self) -> bool {
343        if self.type_id != other.type_id {
344            return false;
345        }
346        // SAFETY: Checked that the two types are the same above.
347        unsafe { self.vtable.eq_fn()(self.bytes.get_bytes_ref(), other.bytes.get_bytes_ref()) }
348    }
349}
350
351impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop + HasPartialEq> Eq for Value<B, V> {}
352
353impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop + HasHash> Hash for Value<B, V> {
354    #[inline]
355    fn hash<H: Hasher>(&self, state: &mut H) {
356        unsafe {
357            self.vtable.hash_fn()(self.bytes.get_bytes_ref(), state);
358        }
359    }
360}
361
362impl<B: GetBytesMut + DropAsAligned, V: ?Sized + HasDrop> Value<B, V> {
363    impl_value_base!();
364}
365
366impl<V: ?Sized + HasDrop> Value<Box<[MaybeUninit<u8>]>, V> {
367    /// Downcast this value reference into a boxed `T` type. Return `None` if the downcast fails.
368    #[inline]
369    pub fn downcast<T: 'static>(self) -> Option<Box<T>> {
370        // Override the Drop implementation, since we don't actually want to drop the contents
371        // here, just the vtable.
372        let mut s = ManuallyDrop::new(self);
373        let output = if s.is::<T>() {
374            // This is safe since we check that self.bytes represents a `T`.
375            Some(unsafe { Bytes::box_from_box_bytes(ManuallyDrop::take(&mut s.bytes)) })
376        } else {
377            None
378        };
379        // We are done with self, dropping the remaining fields here to avoid memory leaks.
380        // This is safe since `s` will not be used again.
381        unsafe {
382            // Note that TypeId is a Copy type and does not need to be manually dropped.
383            ManuallyDrop::drop(&mut s.vtable);
384        }
385        output
386    }
387}
388
389impl<V: ?Sized + HasDrop> Value<MaybeUninit<usize>, V> {
390    /// Downcast this value reference into a boxed `T` type. Return `None` if the downcast fails.
391    #[inline]
392    pub fn downcast<T: 'static>(self) -> Option<T> {
393        // Override the Drop implementation, since we don't actually want to drop the contents
394        // here, just the vtable.
395        let mut s = ManuallyDrop::new(self);
396        // This is safe since we check that self.bytes represent a `T`.
397        let output = if s.is::<T>() {
398            unsafe { Bytes::try_from_usize(ManuallyDrop::take(&mut s.bytes)) }
399        } else {
400            None
401        };
402        // We are done with self, dropping the remaining fields here to avoid memory leaks.
403        // This is safe since `s` will not be used again.
404        unsafe {
405            // Note that TypeId is a Copy type and does not need to be manually dropped.
406            ManuallyDrop::drop(&mut s.vtable);
407        }
408        output
409    }
410}
411
412macro_rules! impl_value_ref_traits {
413    ($value_ref:ident : $($maybe_drop:ident)*) => {
414        unsafe impl<'a, V: ?Sized + HasSend $( + $maybe_drop)*> Send for $value_ref<'a, V> {}
415        unsafe impl<'a, V: ?Sized + HasSync $( + $maybe_drop)*> Sync for $value_ref<'a, V> {}
416
417        impl<'a, V: ?Sized + HasHash $( + $maybe_drop)*> Hash for $value_ref<'a, V> {
418            #[inline]
419            fn hash<H: Hasher>(&self, state: &mut H) {
420                unsafe {
421                    self.vtable.as_ref().hash_fn()(self.bytes.get_bytes_ref(), state);
422                }
423            }
424        }
425
426        impl<'a, V: ?Sized + HasDebug $( + $maybe_drop)*> fmt::Debug for $value_ref<'a, V> {
427            #[inline]
428            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
429                unsafe { self.vtable.as_ref().fmt_fn()(self.bytes.get_bytes_ref(), f) }
430            }
431        }
432
433        impl<'a, V: ?Sized + HasPartialEq $( + $maybe_drop)*> PartialEq for $value_ref<'a, V> {
434            #[inline]
435            fn eq(&self, other: &Self) -> bool {
436                if self.type_id != other.type_id {
437                    return false;
438                }
439                // SAFETY: Checked that the two types are the same above.
440                unsafe {
441                    self.vtable.as_ref().eq_fn()(self.bytes.get_bytes_ref(), other.bytes.get_bytes_ref())
442                }
443            }
444        }
445
446        impl<'a, V: ?Sized + HasEq $( + $maybe_drop)*> Eq for $value_ref<'a, V> {}
447    }
448}
449
450// Impl value ref traits for CopyValue types.
451impl_value_ref_traits!(CopyValueMut:);
452impl_value_ref_traits!(CopyValueRef:);
453
454/// A generic value reference into a buffer.
455#[derive(Clone)]
456pub struct ValueRef<'a, V>
457where
458    V: ?Sized + HasDrop,
459{
460    pub(crate) bytes: &'a [MaybeUninit<u8>],
461    pub(crate) type_id: TypeId,
462    pub(crate) alignment: usize,
463    pub(crate) vtable: VTableRef<'a, V>,
464}
465
466impl_value_ref_traits!(ValueRef: HasDrop);
467
468impl<'a, V: HasDrop> ValueRef<'a, V> {
469    /// Create a new `ValueRef` from a typed reference.
470    #[inline]
471    pub fn new<T: Any + DropBytes>(typed: &'a T) -> ValueRef<'a, V>
472    where
473        V: VTable<T>,
474    {
475        // Reminder: We need DropFn here in case the referenced value is cloned.
476        ValueRef {
477            bytes: typed.as_bytes(),
478            type_id: TypeId::of::<T>(),
479            alignment: std::mem::align_of::<T>(),
480            vtable: VTableRef::Box(Box::new(V::build_vtable())),
481        }
482    }
483}
484
485impl<'a, B: GetBytesMut + DropAsAligned, V> From<&'a Value<B, V>> for ValueRef<'a, V>
486where
487    B: GetBytesRef,
488    V: ?Sized + Clone + HasDrop,
489{
490    fn from(val: &'a Value<B, V>) -> Self {
491        ValueRef {
492            bytes: val.bytes.get_bytes_ref(),
493            type_id: val.type_id,
494            alignment: val.alignment,
495            vtable: Ptr::clone(&val.vtable).into(),
496        }
497    }
498}
499
500impl<'a, V: ?Sized + HasDrop> ValueRef<'a, V> {
501    impl_value_base!();
502
503    /// Create a new `ValueRef` from a slice of bytes and an associated `TypeId`.
504    ///
505    /// # Safety
506    ///
507    /// The given bytes must be the correct representation of the type given `TypeId`.
508    #[inline]
509    pub(crate) unsafe fn from_raw_parts(
510        bytes: &'a [MaybeUninit<u8>],
511        type_id: TypeId,
512        alignment: usize,
513        vtable: impl Into<VTableRef<'a, V>>,
514    ) -> ValueRef<'a, V> {
515        ValueRef {
516            bytes,
517            type_id,
518            alignment,
519            vtable: vtable.into(),
520        }
521    }
522
523    /// Clone the referenced value.
524    ///
525    /// Unlike the `Clone` trait, this function will produce an owned clone of the value pointed to
526    /// by this value reference.
527    #[inline]
528    pub fn clone_value(&self) -> Value<Box<[MaybeUninit<u8>]>, V>
529    where
530        V: HasClone + Clone,
531    {
532        Value {
533            bytes: ManuallyDrop::new(unsafe { self.vtable.as_ref().clone_fn()(self.bytes) }),
534            type_id: self.type_id,
535            alignment: self.alignment,
536            vtable: ManuallyDrop::new(Ptr::from(self.vtable.as_ref().clone())),
537        }
538    }
539
540    /// Clone the referenced value.
541    ///
542    /// Unlike the `Clone` trait, this function will produce an owned clone of the value pointed to
543    /// by this value reference.
544    ///
545    /// This version of `clone_value` tries to fit the underlying value into a `usize` sized value,
546    /// and panics if that fails.
547    #[inline]
548    pub fn clone_small_value(&self) -> Value<MaybeUninit<usize>, V>
549    where
550        V: HasClone + Clone,
551    {
552        let mut bytes = MaybeUninit::uninit();
553        // This is safe because clone_into_raw_fn will not attempt to drop the value at the
554        // destination.
555        unsafe {
556            self.vtable.clone_into_raw_fn()(
557                self.bytes.get_bytes_ref(),
558                Bytes::as_bytes_mut(&mut bytes),
559            );
560        }
561        Value {
562            bytes: ManuallyDrop::new(bytes),
563            type_id: self.type_id,
564            alignment: self.alignment,
565            vtable: ManuallyDrop::new(Ptr::from(self.vtable.as_ref().clone())),
566        }
567    }
568
569    /// Downcast this value reference into a borrowed `T` type. Return `None` if the downcast fails.
570    #[inline]
571    pub fn downcast<T: 'static>(self) -> Option<&'a T> {
572        // This is safe since we check that self.bytes represent a `T`.
573        self.downcast_with::<T, _, _>(|b| unsafe { Bytes::from_bytes(b.bytes) })
574    }
575
576    #[inline]
577    pub fn upcast<U: ?Sized + HasDrop + From<V>>(self) -> ValueRef<'a, U>
578    where
579        V: Clone,
580    {
581        ValueRef {
582            bytes: self.bytes,
583            type_id: self.type_id,
584            alignment: self.alignment,
585            vtable: VTableRef::Box(Box::new(U::from(self.vtable.take()))),
586        }
587    }
588
589    #[inline]
590    pub fn upcast_ref<U: ?Sized + HasDrop + From<V>>(&self) -> ValueRef<U>
591    where
592        V: Clone,
593    {
594        let vtable = self.vtable.as_ref();
595        ValueRef {
596            bytes: self.bytes,
597            type_id: self.type_id,
598            alignment: self.alignment,
599            vtable: VTableRef::Box(Box::new(U::from((*vtable).clone()))),
600        }
601    }
602
603    /// An alternative to `Clone` that doesn't require cloning the vtable.
604    #[inline]
605    pub fn reborrow(&self) -> ValueRef<V> {
606        ValueRef {
607            bytes: &*self.bytes,
608            type_id: self.type_id,
609            alignment: self.alignment,
610            vtable: VTableRef::Ref(self.vtable.as_ref()),
611        }
612    }
613}
614
615/// A generic mutable value reference into a buffer.
616pub struct ValueMut<'a, V>
617where
618    V: ?Sized + HasDrop,
619{
620    pub(crate) bytes: &'a mut [MaybeUninit<u8>],
621    pub(crate) type_id: TypeId,
622    pub(crate) alignment: usize,
623    pub(crate) vtable: VTableRef<'a, V>,
624}
625
626impl_value_ref_traits!(ValueMut: HasDrop);
627
628impl<'a, V: HasDrop> ValueMut<'a, V> {
629    /// Create a new `ValueRef` from a typed reference.
630    #[inline]
631    pub fn new<T: Any>(typed: &'a mut T) -> ValueMut<'a, V>
632    where
633        V: VTable<T>,
634    {
635        ValueMut {
636            bytes: typed.as_bytes_mut(),
637            type_id: TypeId::of::<T>(),
638            alignment: std::mem::align_of::<T>(),
639            vtable: VTableRef::Box(Box::new(V::build_vtable())),
640        }
641    }
642}
643
644impl<'a, V: ?Sized + HasDrop> ValueMut<'a, V> {
645    impl_value_base!();
646
647    /// Swap the values between `other` and `self`.
648    #[inline]
649    pub fn swap<'b>(&mut self, other: &mut ValueMut<'b, V>) {
650        if self.value_type_id() == other.value_type_id() {
651            self.bytes.swap_with_slice(other.bytes);
652        }
653    }
654
655    /// Moves the given value into self.
656    pub fn assign<B: GetBytesMut + DropAsAligned>(&mut self, mut value: Value<B, V>) {
657        // Swapping the values ensures that `value` will not be dropped, but the overwritten value
658        // in self will.
659        self.swap(&mut value.as_mut())
660    }
661
662    /// Clone `other` into `self`.
663    ///
664    /// This function will call `drop` on any values stored in `self`.
665    #[inline]
666    pub fn clone_from_other<'b>(&mut self, other: impl Into<ValueRef<'b, V>>) -> Result<(), Error>
667    where
668        V: HasClone + 'b,
669    {
670        let other = other.into();
671        if self.value_type_id() == other.value_type_id() {
672            unsafe {
673                // We are cloning other.bytes into self.bytes.
674                // This function will call the appropriate typed clone_from function, which will
675                // automatically drop the previous value of self.bytes, so no manual drop call is
676                // needed here.
677                self.vtable.as_ref().clone_from_fn()(self.bytes, other.bytes);
678            }
679            Ok(())
680        } else {
681            Err(Error::MismatchedTypes {
682                expected: self.value_type_id(),
683                actual: other.value_type_id(),
684            })
685        }
686    }
687
688    /// Clone the referenced value.
689    ///
690    /// Unlike the `Clone` trait, this function will produce an owned clone of the value pointed to
691    /// by this value reference.
692    #[inline]
693    pub fn clone_value(&self) -> Value<Box<[MaybeUninit<u8>]>, V>
694    where
695        V: HasClone + Clone,
696    {
697        Value {
698            bytes: ManuallyDrop::new(unsafe { self.vtable.as_ref().clone_fn()(self.bytes) }),
699            type_id: self.type_id,
700            alignment: self.alignment,
701            vtable: ManuallyDrop::new(Ptr::from(self.vtable.as_ref().clone())),
702        }
703    }
704
705    /// Clone the referenced value.
706    ///
707    /// Unlike the `Clone` trait, this function will produce an owned clone of the value pointed to
708    /// by this value reference.
709    ///
710    /// This version of `clone_value` tries to fit the underlying value into a `usize` sized value,
711    /// and panics if that fails.
712    #[inline]
713    pub fn clone_small_value(&self) -> Value<MaybeUninit<usize>, V>
714    where
715        V: HasClone + Clone,
716    {
717        let mut bytes = MaybeUninit::uninit();
718        // This is safe because clone_into_raw_fn will not attempt to drop the value at the
719        // destination.
720        unsafe {
721            self.vtable.clone_into_raw_fn()(
722                self.bytes.get_bytes_ref(),
723                Bytes::as_bytes_mut(&mut bytes),
724            );
725        }
726        Value {
727            bytes: ManuallyDrop::new(bytes),
728            type_id: self.type_id,
729            alignment: self.alignment,
730            vtable: ManuallyDrop::new(Ptr::from(self.vtable.as_ref().clone())),
731        }
732    }
733
734    /// Create a new `ValueMut` from a slice of bytes and an associated `TypeId`.
735    ///
736    /// # Safety
737    ///
738    /// The given bytes must be the correct representation of the type given `TypeId`.
739    #[inline]
740    pub(crate) unsafe fn from_raw_parts(
741        bytes: &'a mut [MaybeUninit<u8>],
742        type_id: TypeId,
743        alignment: usize,
744        vtable: impl Into<VTableRef<'a, V>>,
745    ) -> ValueMut<'a, V> {
746        ValueMut {
747            bytes,
748            type_id,
749            alignment,
750            vtable: vtable.into(),
751        }
752    }
753
754    /// Downcast this value reference into a borrowed `T` type. Return `None` if the downcast fails.
755    #[inline]
756    pub fn downcast<T: 'static>(self) -> Option<&'a mut T> {
757        // This is safe since we check that self.bytes represent a `T`.
758        self.downcast_with::<T, _, _>(|b| unsafe { Bytes::from_bytes_mut(b.bytes) })
759    }
760
761    /// A consuming upcast that carries the lifetime of the underlying value reference.
762    #[inline]
763    pub fn upcast<U: ?Sized + HasDrop + From<V>>(self) -> ValueMut<'a, U>
764    where
765        V: Clone,
766    {
767        ValueMut {
768            bytes: self.bytes,
769            type_id: self.type_id,
770            alignment: self.alignment,
771            vtable: VTableRef::Box(Box::new(U::from(self.vtable.take()))),
772        }
773    }
774
775    /// Create a new mutable value reference upcast from the current one.
776    #[inline]
777    pub fn upcast_mut<U: ?Sized + HasDrop + From<V>>(&mut self) -> ValueMut<U>
778    where
779        V: Clone,
780    {
781        ValueMut {
782            bytes: self.bytes,
783            type_id: self.type_id,
784            alignment: self.alignment,
785            vtable: VTableRef::Box(Box::new(U::from((*self.vtable).clone()))),
786        }
787    }
788
789    #[inline]
790    pub fn reborrow(&self) -> ValueRef<V> {
791        ValueRef {
792            bytes: self.bytes,
793            type_id: self.type_id,
794            alignment: self.alignment,
795            vtable: VTableRef::Ref(self.vtable.as_ref()),
796        }
797    }
798
799    #[inline]
800    pub fn reborrow_mut(&mut self) -> ValueMut<V> {
801        ValueMut {
802            bytes: self.bytes,
803            type_id: self.type_id,
804            alignment: self.alignment,
805            vtable: VTableRef::Ref(self.vtable.as_ref()),
806        }
807    }
808}
809
810/*
811 * Valid conversions.
812 */
813
814impl<'a, V: HasDrop> From<ValueMut<'a, V>> for ValueRef<'a, V> {
815    #[inline]
816    fn from(v: ValueMut<'a, V>) -> ValueRef<'a, V> {
817        ValueRef {
818            bytes: v.bytes,
819            type_id: v.type_id,
820            alignment: v.alignment,
821            vtable: v.vtable,
822        }
823    }
824}
825
826/// Implementation for dropping a copy.
827///
828/// This enables the following two conversions.
829unsafe fn drop_copy(_: &mut [MaybeUninit<u8>]) {}
830
831impl<'a, V: Any + Clone> From<CopyValueMut<'a, V>> for ValueMut<'a, (DropFn, V)> {
832    #[inline]
833    fn from(v: CopyValueMut<'a, V>) -> ValueMut<'a, (DropFn, V)> {
834        ValueMut {
835            bytes: v.bytes,
836            type_id: v.type_id,
837            alignment: v.alignment,
838            vtable: VTableRef::Box(Box::new((drop_copy, v.vtable.take()))),
839        }
840    }
841}
842
843impl<'a, V: Any + Clone> From<CopyValueRef<'a, V>> for ValueRef<'a, (DropFn, V)> {
844    #[inline]
845    fn from(v: CopyValueRef<'a, V>) -> ValueRef<'a, (DropFn, V)> {
846        ValueRef {
847            bytes: v.bytes,
848            type_id: v.type_id,
849            alignment: v.alignment,
850            vtable: VTableRef::Box(Box::new((drop_copy, v.vtable.take()))),
851        }
852    }
853}
854
855#[cfg(test)]
856mod tests {
857    use super::*;
858    use crate::dync_trait;
859    use std::rc::Rc;
860
861    #[dync_trait(dync_crate_name = "crate")]
862    pub trait Val: Clone + PartialEq + Eq + std::hash::Hash + std::fmt::Debug + 'static {}
863    impl<T> Val for T where T: Clone + PartialEq + Eq + std::hash::Hash + std::fmt::Debug + 'static {}
864
865    #[dync_trait(dync_crate_name = "crate")]
866    pub trait Float: Clone + PartialEq + std::fmt::Debug + 'static {}
867    impl<T> Float for T where T: Clone + PartialEq + std::fmt::Debug + 'static {}
868
869    #[test]
870    fn compare_values_with_different_types() {
871        let a = BoxValue::<ValVTable>::new(Rc::new("Hello"));
872        let b = BoxValue::<ValVTable>::new(Rc::new(String::from("Hello")));
873        assert_ne!(a, b);
874    }
875
876    #[test]
877    fn compare_value_ref_with_different_types() {
878        let a = BoxValue::<ValVTable>::new(Rc::new("Hello"));
879        let b = BoxValue::<ValVTable>::new(Rc::new(String::from("Hello")));
880        assert_ne!(a.as_ref(), b.as_ref());
881    }
882
883    #[test]
884    fn compare_value_mut_with_different_types() {
885        let mut a = BoxValue::<ValVTable>::new(Rc::new("Hello"));
886        let mut b = BoxValue::<ValVTable>::new(Rc::new(String::from("Hello")));
887        assert_ne!(a.as_mut(), b.as_mut());
888    }
889
890    #[test]
891    fn values_with_different_types_in_a_hash_set() {
892        use std::collections::HashSet;
893        let mut set_a = HashSet::new();
894        let mut set_b = HashSet::new();
895        let a = BoxValue::<ValVTable>::new(Rc::new("Hello"));
896        let b = BoxValue::<ValVTable>::new(String::from("Hello"));
897        let c = BoxValue::<ValVTable>::new("Hello");
898        set_a.insert(a.clone());
899        set_a.insert(b);
900        set_b.insert(a.clone());
901        set_b.insert(c);
902        let set_intersect = set_a.intersection(&set_b).collect::<HashSet<_>>();
903
904        assert_eq!(set_intersect.len(), 1);
905        let elem = set_intersect.into_iter().next().unwrap();
906        assert_eq!(elem, &a);
907    }
908
909    #[test]
910    fn value_equality() {
911        let a = Rc::new(String::from("Hello"));
912        let b = Rc::new(String::from("Hello"));
913        assert_eq!(&a, &b);
914
915        let a = BoxValue::<ValVTable>::new(Rc::new(String::from("Hello")));
916        let b = BoxValue::<ValVTable>::new(Rc::new(String::from("Hello")));
917        let c = b.clone();
918        let c_rc = b.clone().downcast::<Rc<String>>().unwrap();
919        let d = BoxValue::<ValVTable>::new(Rc::clone(&*c_rc));
920        assert_eq!(&a, &b);
921        assert_eq!(&a, &c);
922        assert_eq!(&a, &d);
923    }
924
925    #[test]
926    fn unaligned_box_value() {
927        let a = [0.0_f32; 3];
928        let a_val = BoxValue::<FloatVTable>::new(a);
929        // Cloning so a_val can be dropped, which tests a proper drop of BoxValue.
930        let b = *a_val.clone().downcast::<[f32; 3]>().unwrap();
931        assert_eq!(&a, &b);
932    }
933
934    // This test checks that cloning and dropping clones works correctly.
935    #[test]
936    fn clone_test() {
937        let val = BoxValue::<ValVTable>::new(Rc::new(1u8));
938        assert_eq!(&val, &val.clone());
939    }
940
941    // This test checks that cloning and dropping clones works correctly.
942    #[test]
943    fn clone_small_test() {
944        let val = SmallValue::<ValVTable>::new(Rc::new(1u8));
945        assert_eq!(&val, &val.clone());
946    }
947
948    // Test that we can convert from a copy value to a regular value.
949    #[test]
950    fn copy_value_to_value_convert() {
951        // make a vector and get a reference value from it.
952        let v = crate::vec_copy::VecCopy::from(vec![1u32, 2, 3]);
953        let copy_val = v.get_ref(1);
954        let val: ValueRef<(DropFn, ())> = copy_val.into();
955        assert_eq!(val.downcast::<u32>().unwrap(), &2u32);
956    }
957}