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
75#[cfg(rust_analyzer)]
79impl<U> std::ops::Deref for TraitRef<Box<U>>
80where
81 U: ?Sized,
82 Box<U>: VcValueTrait,
83{
84 type Target = U;
85
86 fn deref(&self) -> &Self::Target {
87 unimplemented!("only exists for rust-analyzer type inference")
88 }
89}
90
91#[cfg(not(rust_analyzer))]
92impl<U> std::ops::Deref for TraitRef<Box<U>>
93where
94 Box<U>: VcValueTrait<ValueTrait = U>,
95 U: std::ptr::Pointee<Metadata = std::ptr::DynMetadata<U>> + ?Sized,
96{
97 type Target = U;
98
99 fn deref(&self) -> &Self::Target {
100 let metadata =
103 <Box<U> as VcValueTrait>::get_impl_vtables().get(self.shared_reference.type_id);
104 let downcast_ptr = std::ptr::from_raw_parts(
105 self.shared_reference.reference.0.as_ptr() as *const (),
106 metadata,
107 );
108 unsafe { &*downcast_ptr }
109 }
110}
111
112unsafe impl<T> Sync for TraitRef<T> where T: ?Sized {}
115
116unsafe impl<T> Send for TraitRef<T> where T: ?Sized {}
119
120impl<T> Unpin for TraitRef<T> where T: ?Sized {}
121
122impl<T> TraitRef<T>
123where
124 T: ?Sized,
125{
126 pub(crate) fn new(shared_reference: TypedSharedReference) -> Self {
127 Self {
128 shared_reference,
129 _t: PhantomData,
130 }
131 }
132
133 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
134 triomphe::Arc::ptr_eq(
135 &this.shared_reference.reference.0,
136 &other.shared_reference.reference.0,
137 )
138 }
139}
140
141impl<T> TraitRef<T>
142where
143 T: VcValueTrait + ?Sized,
144{
145 pub fn cell(trait_ref: TraitRef<T>) -> Vc<T> {
148 let TraitRef {
149 shared_reference, ..
150 } = trait_ref;
151 let value_type = get_value_type(shared_reference.type_id);
152 (value_type.raw_cell)(shared_reference).into()
153 }
154}
155
156pub trait IntoTraitRef {
163 type ValueTrait: VcValueTrait + ?Sized;
164 type Future: Future<Output = Result<<VcValueTraitCast<Self::ValueTrait> as VcCast>::Output>>;
165
166 fn into_trait_ref(self) -> Self::Future;
167}
168
169impl<T> IntoTraitRef for Vc<T>
170where
171 T: VcValueTrait + ?Sized,
172{
173 type ValueTrait = T;
174
175 type Future = ReadVcFuture<T, VcValueTraitCast<T>>;
176
177 fn into_trait_ref(self) -> Self::Future {
178 self.node.into_read().into()
179 }
180}