1use std::{fmt::Debug, future::Future, marker::PhantomData};
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 Vc, VcValueTrait,
8 registry::get_value_type,
9 task::shared_reference::TypedSharedReference,
10 vc::{ReadVcFuture, VcValueTraitCast, cast::VcCast},
11};
12
13pub struct TraitRef<T>
22where
23 T: ?Sized,
24{
25 shared_reference: TypedSharedReference,
26 _t: PhantomData<T>,
27}
28
29impl<T> Debug for TraitRef<T> {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 f.debug_struct("TraitRef")
32 .field("shared_reference", &self.shared_reference)
33 .finish()
34 }
35}
36
37impl<T> Clone for TraitRef<T> {
38 fn clone(&self) -> Self {
39 Self {
40 shared_reference: self.shared_reference.clone(),
41 _t: PhantomData,
42 }
43 }
44}
45
46impl<T> PartialEq for TraitRef<T> {
47 fn eq(&self, other: &Self) -> bool {
48 self.shared_reference == other.shared_reference
49 }
50}
51
52impl<T> Eq for TraitRef<T> {}
53
54impl<T> std::hash::Hash for TraitRef<T> {
55 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
56 self.shared_reference.hash(state)
57 }
58}
59
60impl<T> Serialize for TraitRef<T> {
61 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
62 self.shared_reference.serialize(serializer)
63 }
64}
65
66impl<'de, T> Deserialize<'de> for TraitRef<T> {
67 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
68 Ok(Self {
69 shared_reference: TypedSharedReference::deserialize(deserializer)?,
70 _t: PhantomData,
71 })
72 }
73}
74
75impl<U> std::ops::Deref for TraitRef<Box<U>>
76where
77 Box<U>: VcValueTrait<ValueTrait = U>,
78 U: std::ptr::Pointee<Metadata = std::ptr::DynMetadata<U>> + ?Sized,
79{
80 type Target = U;
81
82 fn deref(&self) -> &Self::Target {
83 let downcast_ptr = <Box<U> as VcValueTrait>::get_impl_vtables().cast(
86 self.shared_reference.type_id,
87 self.shared_reference.reference.0.as_ptr() as *const (),
88 );
89 unsafe { &*downcast_ptr }
91 }
92}
93
94unsafe impl<T> Sync for TraitRef<T> where T: ?Sized {}
97
98unsafe impl<T> Send for TraitRef<T> where T: ?Sized {}
101
102impl<T> Unpin for TraitRef<T> where T: ?Sized {}
103
104impl<T> TraitRef<T>
105where
106 T: ?Sized,
107{
108 pub(crate) fn new(shared_reference: TypedSharedReference) -> Self {
109 Self {
110 shared_reference,
111 _t: PhantomData,
112 }
113 }
114
115 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
116 triomphe::Arc::ptr_eq(
117 &this.shared_reference.reference.0,
118 &other.shared_reference.reference.0,
119 )
120 }
121}
122
123impl<T> TraitRef<T>
124where
125 T: VcValueTrait + ?Sized,
126{
127 pub fn cell(trait_ref: TraitRef<T>) -> Vc<T> {
130 let TraitRef {
131 shared_reference, ..
132 } = trait_ref;
133 let value_type = get_value_type(shared_reference.type_id);
134 (value_type.raw_cell)(shared_reference).into()
135 }
136}
137
138pub trait IntoTraitRef {
145 type ValueTrait: VcValueTrait + ?Sized;
146 type Future: Future<Output = Result<<VcValueTraitCast<Self::ValueTrait> as VcCast>::Output>>;
147
148 fn into_trait_ref(self) -> Self::Future;
149}
150
151impl<T> IntoTraitRef for Vc<T>
152where
153 T: VcValueTrait + ?Sized,
154{
155 type ValueTrait = T;
156
157 type Future = ReadVcFuture<T, VcValueTraitCast<T>>;
158
159 fn into_trait_ref(self) -> Self::Future {
160 self.node.into_read().into()
161 }
162}