1#![allow(dead_code)]
7
8use std::any::{Any, TypeId};
9use std::fmt;
10use std::hash::{Hash, Hasher};
11use std::mem::{ManuallyDrop, MaybeUninit};
12
13use 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 ValueTooLarge,
26 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
56impl<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 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 #[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 #[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 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 unsafe {
175 ManuallyDrop::drop(&mut md.vtable);
176 }
177
178 output
179 }
180
181 #[inline]
185 pub fn into_raw_parts(self) -> (MaybeUninit<usize>, TypeId, usize, Ptr<V>) {
186 let mut md = ManuallyDrop::new(self);
188
189 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 #[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 let mut md = ManuallyDrop::new(self);
242 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 unsafe {
254 ManuallyDrop::drop(&mut md.vtable);
255 }
256
257 output
258 }
259
260 #[inline]
264 pub fn into_raw_parts(self) -> (Box<[MaybeUninit<u8>]>, TypeId, usize, Ptr<V>) {
265 let mut md = ManuallyDrop::new(self);
267
268 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 self.vtable.drop_fn()(self.bytes.get_bytes_mut());
329
330 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 #[inline]
342 fn eq(&self, other: &Self) -> bool {
343 if self.type_id != other.type_id {
344 return false;
345 }
346 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 #[inline]
369 pub fn downcast<T: 'static>(self) -> Option<Box<T>> {
370 let mut s = ManuallyDrop::new(self);
373 let output = if s.is::<T>() {
374 Some(unsafe { Bytes::box_from_box_bytes(ManuallyDrop::take(&mut s.bytes)) })
376 } else {
377 None
378 };
379 unsafe {
382 ManuallyDrop::drop(&mut s.vtable);
384 }
385 output
386 }
387}
388
389impl<V: ?Sized + HasDrop> Value<MaybeUninit<usize>, V> {
390 #[inline]
392 pub fn downcast<T: 'static>(self) -> Option<T> {
393 let mut s = ManuallyDrop::new(self);
396 let output = if s.is::<T>() {
398 unsafe { Bytes::try_from_usize(ManuallyDrop::take(&mut s.bytes)) }
399 } else {
400 None
401 };
402 unsafe {
405 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 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
450impl_value_ref_traits!(CopyValueMut:);
452impl_value_ref_traits!(CopyValueRef:);
453
454#[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 #[inline]
471 pub fn new<T: Any + DropBytes>(typed: &'a T) -> ValueRef<'a, V>
472 where
473 V: VTable<T>,
474 {
475 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 #[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 #[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 #[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 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 #[inline]
571 pub fn downcast<T: 'static>(self) -> Option<&'a T> {
572 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 #[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
615pub 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 #[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 #[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 pub fn assign<B: GetBytesMut + DropAsAligned>(&mut self, mut value: Value<B, V>) {
657 self.swap(&mut value.as_mut())
660 }
661
662 #[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 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 #[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 #[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 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 #[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 #[inline]
756 pub fn downcast<T: 'static>(self) -> Option<&'a mut T> {
757 self.downcast_with::<T, _, _>(|b| unsafe { Bytes::from_bytes_mut(b.bytes) })
759 }
760
761 #[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 #[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
810impl<'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
826unsafe 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 let b = *a_val.clone().downcast::<[f32; 3]>().unwrap();
931 assert_eq!(&a, &b);
932 }
933
934 #[test]
936 fn clone_test() {
937 let val = BoxValue::<ValVTable>::new(Rc::new(1u8));
938 assert_eq!(&val, &val.clone());
939 }
940
941 #[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]
950 fn copy_value_to_value_convert() {
951 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}