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