turbo_tasks/task/
shared_reference.rs1use std::{
2 any::Any,
3 fmt::{Debug, Display},
4 hash::Hash,
5 ops::Deref,
6};
7
8use anyhow::Result;
9use bincode::{
10 Decode, Encode,
11 error::{DecodeError, EncodeError},
12 impl_borrow_decode,
13};
14use turbo_bincode::{
15 TurboBincodeDecode, TurboBincodeDecoder, TurboBincodeEncode, TurboBincodeEncoder,
16 impl_decode_for_turbo_bincode_decode, impl_encode_for_turbo_bincode_encode,
17};
18use unsize::CoerceUnsize;
19
20use crate::{
21 ValueType, ValueTypeId, registry,
22 triomphe_utils::{coerce_to_any_send_sync, downcast_triomphe_arc},
23};
24
25#[derive(Clone)]
27pub struct SharedReference(pub triomphe::Arc<dyn Any + Send + Sync>);
28
29impl SharedReference {
30 pub fn new(data: triomphe::Arc<impl Any + Send + Sync>) -> Self {
31 Self(data.unsize(coerce_to_any_send_sync()))
32 }
33}
34
35#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
37pub struct TypedSharedReference {
38 pub type_id: ValueTypeId,
39 pub reference: SharedReference,
40}
41
42impl SharedReference {
43 pub fn downcast<T: Any + Send + Sync>(self) -> Result<triomphe::Arc<T>, Self> {
44 match downcast_triomphe_arc(self.0) {
45 Ok(data) => Ok(data),
46 Err(data) => Err(Self(data)),
47 }
48 }
49
50 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
51 self.0.downcast_ref()
52 }
53
54 pub fn into_typed(self, type_id: ValueTypeId) -> TypedSharedReference {
55 TypedSharedReference {
56 type_id,
57 reference: self,
58 }
59 }
60}
61
62impl TypedSharedReference {
63 pub fn into_untyped(self) -> SharedReference {
64 self.reference
65 }
66}
67
68impl TurboBincodeEncode for TypedSharedReference {
69 fn encode(&self, encoder: &mut TurboBincodeEncoder) -> Result<(), EncodeError> {
70 let Self { type_id, reference } = self;
71 let value_type = registry::get_value_type(*type_id);
72 if let Some(bincode) = value_type.bincode {
73 type_id.encode(encoder)?;
74 bincode.0(&*reference.0, encoder)?;
75 Ok(())
76 } else {
77 Err(EncodeError::OtherString(format!(
78 "{} is not encodable",
79 value_type.global_name
80 )))
81 }
82 }
83}
84
85impl<Context> TurboBincodeDecode<Context> for TypedSharedReference {
86 fn decode(decoder: &mut TurboBincodeDecoder) -> Result<Self, DecodeError> {
87 let type_id = ValueTypeId::decode(decoder)?;
88 let value_type = registry::get_value_type(type_id);
89 if let Some(bincode) = value_type.bincode {
90 let reference = bincode.1(decoder)?;
91 Ok(Self { type_id, reference })
92 } else {
93 #[cold]
94 fn not_decodable(value_type: &ValueType) -> DecodeError {
95 DecodeError::OtherString(format!("{} is not decodable", value_type.global_name))
96 }
97 Err(not_decodable(value_type))
98 }
99 }
100}
101
102impl_encode_for_turbo_bincode_encode!(TypedSharedReference);
103impl_decode_for_turbo_bincode_decode!(TypedSharedReference);
104impl_borrow_decode!(TypedSharedReference);
105
106impl Deref for TypedSharedReference {
107 type Target = SharedReference;
108
109 fn deref(&self) -> &Self::Target {
110 &self.reference
111 }
112}
113
114impl Hash for SharedReference {
115 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
116 Hash::hash(&(&*self.0 as *const (dyn Any + Send + Sync)), state)
117 }
118}
119impl PartialEq for SharedReference {
120 #[allow(ambiguous_wide_pointer_comparisons)]
123 fn eq(&self, other: &Self) -> bool {
124 triomphe::Arc::ptr_eq(&self.0, &other.0)
125 }
126}
127impl Eq for SharedReference {}
128impl PartialOrd for SharedReference {
129 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
130 Some(self.cmp(other))
131 }
132}
133impl Ord for SharedReference {
134 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
135 Ord::cmp(
136 &(&*self.0 as *const (dyn Any + Send + Sync)).cast::<()>(),
137 &(&*other.0 as *const (dyn Any + Send + Sync)).cast::<()>(),
138 )
139 }
140}
141impl Debug for SharedReference {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 f.debug_tuple("SharedReference").field(&self.0).finish()
144 }
145}
146
147impl Display for SharedReference {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 write!(f, "untyped value")
150 }
151}
152
153impl Display for TypedSharedReference {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 write!(
156 f,
157 "value of type {}",
158 registry::get_value_type(self.type_id).name
159 )
160 }
161}