1use std::{fmt::Debug, marker::PhantomData};
2
3use crate::{
4 Vc, VcValueTrait, registry::get_value_type, task::shared_reference::TypedSharedReference,
5};
6
7pub struct TraitRef<T>
15where
16 T: ?Sized,
17{
18 shared_reference: TypedSharedReference,
19 _t: PhantomData<T>,
20}
21
22impl<T> Debug for TraitRef<T> {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 f.debug_struct("TraitRef")
25 .field("shared_reference", &self.shared_reference)
26 .finish()
27 }
28}
29
30impl<T> Clone for TraitRef<T> {
31 fn clone(&self) -> Self {
32 Self {
33 shared_reference: self.shared_reference.clone(),
34 _t: PhantomData,
35 }
36 }
37}
38
39impl<T> PartialEq for TraitRef<T> {
40 fn eq(&self, other: &Self) -> bool {
41 self.shared_reference == other.shared_reference
42 }
43}
44
45impl<T> Eq for TraitRef<T> {}
46
47impl<T> std::hash::Hash for TraitRef<T> {
48 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
49 self.shared_reference.hash(state)
50 }
51}
52
53impl<U> std::ops::Deref for TraitRef<Box<U>>
54where
55 Box<U>: VcValueTrait<ValueTrait = U>,
56 U: std::ptr::Pointee<Metadata = std::ptr::DynMetadata<U>> + ?Sized,
57{
58 type Target = U;
59
60 fn deref(&self) -> &Self::Target {
61 let downcast_ptr = <Box<U> as VcValueTrait>::get_impl_vtables().cast(
64 self.shared_reference.type_id,
65 self.shared_reference.reference.0.as_ptr() as *const (),
66 );
67 unsafe { &*downcast_ptr }
69 }
70}
71
72unsafe impl<T> Sync for TraitRef<T> where T: ?Sized {}
75
76unsafe impl<T> Send for TraitRef<T> where T: ?Sized {}
79
80impl<T> Unpin for TraitRef<T> where T: ?Sized {}
81
82impl<T> TraitRef<T>
83where
84 T: ?Sized,
85{
86 pub(crate) fn new(shared_reference: TypedSharedReference) -> Self {
87 Self {
88 shared_reference,
89 _t: PhantomData,
90 }
91 }
92
93 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
94 triomphe::Arc::ptr_eq(
95 &this.shared_reference.reference.0,
96 &other.shared_reference.reference.0,
97 )
98 }
99}
100
101impl<T> TraitRef<T>
102where
103 T: VcValueTrait + ?Sized,
104{
105 pub fn cell(trait_ref: TraitRef<T>) -> Vc<T> {
108 let TraitRef {
109 shared_reference, ..
110 } = trait_ref;
111 let value_type = get_value_type(shared_reference.type_id);
112 (value_type.raw_cell)(shared_reference).into()
113 }
114}