1use std::{
2 any::{Any, type_name},
3 fmt::{self, Debug, Display, Formatter},
4 hash::Hash,
5 sync::Arc,
6};
7
8use auto_hash_map::{AutoMap, AutoSet};
9use serde::{Deserialize, Serialize};
10use tracing::Span;
11
12use crate::{
13 RawVc, VcValueType,
14 id::TraitTypeId,
15 macro_helpers::NativeFunction,
16 magic_any::{AnyDeserializeSeed, MagicAny, MagicAnyDeserializeSeed},
17 registry::{self, register_trait_type, register_value_type},
18 task::shared_reference::TypedSharedReference,
19 vc::VcCellMode,
20};
21
22type MagicSerializationFn = fn(&dyn MagicAny) -> &dyn erased_serde::Serialize;
23type AnySerializationFn = fn(&(dyn Any + Sync + Send)) -> &dyn erased_serde::Serialize;
24type RawCellFactoryFn = fn(TypedSharedReference) -> RawVc;
25
26pub struct ValueType {
36 pub name: String,
38 traits: AutoSet<TraitTypeId>,
40 trait_methods: AutoMap<&'static TraitMethod, &'static NativeFunction>,
42
43 magic_serialization: Option<(MagicSerializationFn, MagicAnyDeserializeSeed)>,
45 any_serialization: Option<(AnySerializationFn, AnyDeserializeSeed)>,
46
47 pub(crate) raw_cell: RawCellFactoryFn,
57}
58
59impl Hash for ValueType {
60 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
61 (self as *const ValueType).hash(state);
62 }
63}
64
65impl Eq for ValueType {}
66
67impl PartialEq for ValueType {
68 fn eq(&self, other: &Self) -> bool {
69 std::ptr::eq(self, other)
70 }
71}
72
73impl Debug for ValueType {
74 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
75 let mut d = f.debug_struct("ValueType");
76 d.field("name", &self.name);
77 for trait_id in self.traits.iter() {
78 for (name, m) in ®istry::get_trait(*trait_id).methods {
79 if self.trait_methods.contains_key(&m) {
80 d.field(name, &"(trait fn)");
81 }
82 }
83 }
84 d.finish()
85 }
86}
87
88impl Display for ValueType {
89 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
90 f.write_str(&self.name)
91 }
92}
93
94pub fn any_as_serialize<T: Any + Serialize + Send + Sync + 'static>(
95 this: &(dyn Any + Send + Sync),
96) -> &dyn erased_serde::Serialize {
97 if let Some(r) = this.downcast_ref::<T>() {
98 return r;
99 }
100 panic!(
101 "any_as_serialize::<{}> called with invalid type",
102 type_name::<T>()
103 );
104}
105
106impl ValueType {
107 pub fn new<T: VcValueType>() -> Self {
109 Self {
110 name: std::any::type_name::<T>().to_string(),
111 traits: AutoSet::new(),
112 trait_methods: AutoMap::new(),
113 magic_serialization: None,
114 any_serialization: None,
115 raw_cell: <T::CellMode as VcCellMode<T>>::raw_cell,
116 }
117 }
118
119 pub fn new_with_any_serialization<
121 T: VcValueType + Any + Serialize + for<'de> Deserialize<'de>,
122 >() -> Self {
123 Self {
124 name: std::any::type_name::<T>().to_string(),
125 traits: AutoSet::new(),
126 trait_methods: AutoMap::new(),
127 magic_serialization: None,
128 any_serialization: Some((any_as_serialize::<T>, AnyDeserializeSeed::new::<T>())),
129 raw_cell: <T::CellMode as VcCellMode<T>>::raw_cell,
130 }
131 }
132
133 pub fn magic_as_serializable<'a>(
134 &self,
135 arc: &'a Arc<dyn MagicAny>,
136 ) -> Option<&'a dyn erased_serde::Serialize> {
137 if let Some(s) = self.magic_serialization {
138 let r: &dyn MagicAny = arc;
139 Some((s.0)(r))
140 } else {
141 None
142 }
143 }
144
145 pub fn any_as_serializable<'a>(
146 &self,
147 arc: &'a triomphe::Arc<dyn Any + Sync + Send>,
148 ) -> Option<&'a dyn erased_serde::Serialize> {
149 if let Some(s) = self.any_serialization {
150 Some((s.0)(&**arc))
151 } else {
152 None
153 }
154 }
155
156 pub fn is_serializable(&self) -> bool {
157 self.any_serialization.is_some()
158 }
159
160 pub fn get_magic_deserialize_seed(&self) -> Option<MagicAnyDeserializeSeed> {
161 self.magic_serialization.map(|s| s.1)
162 }
163
164 pub fn get_any_deserialize_seed(&self) -> Option<AnyDeserializeSeed> {
165 self.any_serialization.map(|s| s.1)
166 }
167
168 pub fn register_trait_method(
170 &mut self,
171 trait_type: TraitTypeId,
172 name: &str,
173 native_fn: &'static NativeFunction,
174 ) {
175 self.trait_methods
176 .insert(registry::get_trait(trait_type).get(name), native_fn);
177 }
178
179 pub fn get_trait_method(
180 &self,
181 trait_method: &'static TraitMethod,
182 ) -> Option<&'static NativeFunction> {
183 match self.trait_methods.get(trait_method) {
184 Some(f) => Some(*f),
185 None => trait_method.default_method,
186 }
187 }
188
189 pub fn register_trait(&mut self, trait_type: TraitTypeId) {
191 self.traits.insert(trait_type);
192 }
193
194 pub fn has_trait(&self, trait_type: &TraitTypeId) -> bool {
195 self.traits.contains(trait_type)
196 }
197
198 pub fn traits_iter(&self) -> impl Iterator<Item = TraitTypeId> + '_ {
199 self.traits.iter().cloned()
200 }
201
202 pub fn register(
203 &'static self,
204 global_name: &'static str,
205 register_traits: impl FnOnce(crate::ValueTypeId),
206 ) {
207 let id = register_value_type(global_name, self);
208 if let Some(id) = id {
209 register_traits(id);
210 }
211 }
212}
213
214pub struct TraitMethod {
215 pub(crate) trait_name: &'static str,
216 pub(crate) method_name: &'static str,
217 pub(crate) default_method: Option<&'static NativeFunction>,
218}
219impl Hash for TraitMethod {
220 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
221 (self as *const TraitMethod).hash(state);
222 }
223}
224
225impl Eq for TraitMethod {}
226
227impl PartialEq for TraitMethod {
228 fn eq(&self, other: &Self) -> bool {
229 std::ptr::eq(self, other)
230 }
231}
232impl Debug for TraitMethod {
233 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
234 f.debug_struct("TraitMethod")
235 .field("trait_name", &self.trait_name)
236 .field("name", &self.method_name)
237 .field("default_method", &self.default_method)
238 .finish()
239 }
240}
241impl TraitMethod {
242 pub(crate) fn resolve_span(&self) -> Span {
243 tracing::trace_span!(
244 "turbo_tasks::resolve_trait_call",
245 name = format_args!("{}::{}", &self.trait_name, &self.method_name),
246 )
247 }
248}
249#[derive(Debug)]
250pub struct TraitType {
251 pub name: &'static str,
252 pub(crate) methods: AutoMap<&'static str, TraitMethod>,
253}
254
255impl Hash for TraitType {
256 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
257 (self as *const TraitType).hash(state);
258 }
259}
260
261impl Display for TraitType {
262 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
263 write!(f, "trait {}", self.name)
264 }
265}
266
267impl Eq for TraitType {}
268
269impl PartialEq for TraitType {
270 fn eq(&self, other: &Self) -> bool {
271 std::ptr::eq(self, other)
272 }
273}
274
275impl TraitType {
276 pub fn new(name: &'static str) -> Self {
277 Self {
278 name,
279 methods: AutoMap::new(),
280 }
281 }
282
283 pub fn register_trait_method(&mut self, name: &'static str) {
284 self.methods.insert(
285 name,
286 TraitMethod {
287 trait_name: self.name,
288 method_name: name,
289 default_method: None,
290 },
291 );
292 }
293
294 pub fn register_default_trait_method(
295 &mut self,
296 name: &'static str,
297 native_fn: &'static NativeFunction,
298 ) {
299 self.methods.insert(
300 name,
301 TraitMethod {
302 trait_name: self.name,
303 method_name: name,
304 default_method: Some(native_fn),
305 },
306 );
307 }
308
309 pub fn get(&self, name: &str) -> &TraitMethod {
310 self.methods.get(name).unwrap()
311 }
312
313 pub fn register(&'static self, global_name: &'static str) {
314 register_trait_type(global_name, self);
315 }
316}