1use std::{fmt::Debug, future::Future, marker::PhantomData};
2
3use anyhow::Result;
4
5use crate::{
6 Vc, VcValueTrait,
7 registry::get_value_type,
8 task::shared_reference::TypedSharedReference,
9 vc::{ReadVcFuture, VcValueTraitCast, cast::VcCast},
10};
11
12pub struct TraitRef<T>
21where
22 T: ?Sized,
23{
24 shared_reference: TypedSharedReference,
25 _t: PhantomData<T>,
26}
27
28impl<T> Debug for TraitRef<T> {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 f.debug_struct("TraitRef")
31 .field("shared_reference", &self.shared_reference)
32 .finish()
33 }
34}
35
36impl<T> Clone for TraitRef<T> {
37 fn clone(&self) -> Self {
38 Self {
39 shared_reference: self.shared_reference.clone(),
40 _t: PhantomData,
41 }
42 }
43}
44
45impl<T> PartialEq for TraitRef<T> {
46 fn eq(&self, other: &Self) -> bool {
47 self.shared_reference == other.shared_reference
48 }
49}
50
51impl<T> Eq for TraitRef<T> {}
52
53impl<T> std::hash::Hash for TraitRef<T> {
54 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
55 self.shared_reference.hash(state)
56 }
57}
58
59impl<U> std::ops::Deref for TraitRef<Box<U>>
60where
61 Box<U>: VcValueTrait<ValueTrait = U>,
62 U: std::ptr::Pointee<Metadata = std::ptr::DynMetadata<U>> + ?Sized,
63{
64 type Target = U;
65
66 fn deref(&self) -> &Self::Target {
67 let downcast_ptr = <Box<U> as VcValueTrait>::get_impl_vtables().cast(
70 self.shared_reference.type_id,
71 self.shared_reference.reference.0.as_ptr() as *const (),
72 );
73 unsafe { &*downcast_ptr }
75 }
76}
77
78unsafe impl<T> Sync for TraitRef<T> where T: ?Sized {}
81
82unsafe impl<T> Send for TraitRef<T> where T: ?Sized {}
85
86impl<T> Unpin for TraitRef<T> where T: ?Sized {}
87
88impl<T> TraitRef<T>
89where
90 T: ?Sized,
91{
92 pub(crate) fn new(shared_reference: TypedSharedReference) -> Self {
93 Self {
94 shared_reference,
95 _t: PhantomData,
96 }
97 }
98
99 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
100 triomphe::Arc::ptr_eq(
101 &this.shared_reference.reference.0,
102 &other.shared_reference.reference.0,
103 )
104 }
105}
106
107impl<T> TraitRef<T>
108where
109 T: VcValueTrait + ?Sized,
110{
111 pub fn cell(trait_ref: TraitRef<T>) -> Vc<T> {
114 let TraitRef {
115 shared_reference, ..
116 } = trait_ref;
117 let value_type = get_value_type(shared_reference.type_id);
118 (value_type.raw_cell)(shared_reference).into()
119 }
120}
121
122pub trait IntoTraitRef {
129 type ValueTrait: VcValueTrait + ?Sized;
130 type Future: Future<Output = Result<<VcValueTraitCast<Self::ValueTrait> as VcCast>::Output>>;
131
132 fn into_trait_ref(self) -> Self::Future;
133}
134
135impl<T> IntoTraitRef for Vc<T>
136where
137 T: VcValueTrait + ?Sized,
138{
139 type ValueTrait = T;
140
141 type Future = ReadVcFuture<T, VcValueTraitCast<T>>;
142
143 fn into_trait_ref(self) -> Self::Future {
144 self.node
145 .into_read_with_unknown_is_serializable_cell_content()
146 .into()
147 }
148}