turbo_tasks/
value.rs

1use std::{fmt::Debug, marker::PhantomData, ops::Deref};
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5
6use crate::{
7    ReadRef, SharedReference,
8    debug::{ValueDebugFormat, ValueDebugString},
9    trace::{TraceRawVcs, TraceRawVcsContext},
10};
11
12/// Pass a value by value (`Value<Xxx>`) instead of by reference (`Vc<Xxx>`).
13///
14/// Persistent, requires serialization.
15#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
16pub struct Value<T> {
17    inner: T,
18}
19
20impl<T> Value<T> {
21    pub fn new(value: T) -> Self {
22        Self { inner: value }
23    }
24
25    pub fn into_value(self) -> T {
26        self.inner
27    }
28}
29
30impl<T> Deref for Value<T> {
31    type Target = T;
32
33    fn deref(&self) -> &Self::Target {
34        &self.inner
35    }
36}
37
38impl<T: Copy> Copy for Value<T> {}
39
40impl<T: Default> Default for Value<T> {
41    fn default() -> Self {
42        Value::new(Default::default())
43    }
44}
45
46impl<T: ValueDebugFormat> Value<T> {
47    pub async fn dbg(&self) -> Result<ReadRef<ValueDebugString>> {
48        self.dbg_depth(usize::MAX).await
49    }
50
51    pub async fn dbg_depth(&self, depth: usize) -> Result<ReadRef<ValueDebugString>> {
52        self.inner
53            .value_debug_format(depth)
54            .try_to_value_debug_string()
55            .await?
56            .await
57    }
58}
59
60impl<T: TraceRawVcs> TraceRawVcs for Value<T> {
61    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
62        self.inner.trace_raw_vcs(trace_context)
63    }
64}
65
66/// Pass a value by value (`Value<Xxx>`) instead of by reference (`Vc<Xxx>`).
67///
68/// Doesn't require serialization, and won't be stored in the persistent cache
69/// in the future.
70#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
71pub struct TransientValue<T> {
72    inner: T,
73}
74
75impl<T> TransientValue<T> {
76    pub fn new(value: T) -> Self {
77        Self { inner: value }
78    }
79
80    pub fn into_value(self) -> T {
81        self.inner
82    }
83}
84
85impl<T> Deref for TransientValue<T> {
86    type Target = T;
87
88    fn deref(&self) -> &Self::Target {
89        &self.inner
90    }
91}
92
93impl<T: TraceRawVcs> TraceRawVcs for TransientValue<T> {
94    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
95        self.inner.trace_raw_vcs(trace_context)
96    }
97}
98
99/// Pass a reference to an instance to a turbo-tasks function.
100///
101/// Equality and hash is implemented as pointer comparison.
102///
103/// Doesn't require serialization, and won't be stored in the persistent cache
104/// in the future, so we don't include the `ValueTypeId` in the
105/// `SharedReference`.
106pub struct TransientInstance<T> {
107    inner: SharedReference,
108    phantom: PhantomData<T>,
109}
110
111impl<T> Debug for TransientInstance<T> {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        f.debug_tuple("TransientInstance").finish()
114    }
115}
116
117impl<T> Clone for TransientInstance<T> {
118    fn clone(&self) -> Self {
119        Self {
120            inner: self.inner.clone(),
121            phantom: self.phantom,
122        }
123    }
124}
125
126impl<T> Eq for TransientInstance<T> {}
127
128impl<T> PartialEq for TransientInstance<T> {
129    fn eq(&self, other: &Self) -> bool {
130        self.inner == other.inner
131    }
132}
133
134impl<T> std::hash::Hash for TransientInstance<T> {
135    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
136        self.inner.hash(state);
137    }
138}
139
140impl<T: Send + Sync + 'static> From<TransientInstance<T>> for triomphe::Arc<T> {
141    fn from(instance: TransientInstance<T>) -> Self {
142        // we know this downcast must work because we have type T
143        instance.inner.downcast().unwrap()
144    }
145}
146
147impl<T: Send + Sync + 'static> From<TransientInstance<T>> for SharedReference {
148    fn from(instance: TransientInstance<T>) -> Self {
149        instance.inner
150    }
151}
152
153impl<T: Send + Sync + 'static> From<triomphe::Arc<T>> for TransientInstance<T> {
154    fn from(arc: triomphe::Arc<T>) -> Self {
155        Self {
156            inner: SharedReference::new(arc),
157            phantom: PhantomData,
158        }
159    }
160}
161
162impl<T: Send + Sync + 'static> TryFrom<SharedReference> for TransientInstance<T> {
163    type Error = ();
164
165    fn try_from(inner: SharedReference) -> Result<Self, Self::Error> {
166        if inner.0.downcast_ref::<T>().is_some() {
167            Ok(Self {
168                inner,
169                phantom: PhantomData,
170            })
171        } else {
172            Err(())
173        }
174    }
175}
176
177impl<T: Send + Sync + 'static> TransientInstance<T> {
178    pub fn new(value: T) -> Self {
179        Self {
180            inner: SharedReference::new(triomphe::Arc::new(value)),
181            phantom: PhantomData,
182        }
183    }
184}
185
186impl<T: 'static> Deref for TransientInstance<T> {
187    type Target = T;
188
189    fn deref(&self) -> &Self::Target {
190        self.inner.0.downcast_ref().unwrap()
191    }
192}
193
194impl<T: TraceRawVcs + 'static> TraceRawVcs for TransientInstance<T> {
195    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
196        self.inner.downcast_ref::<T>().trace_raw_vcs(trace_context)
197    }
198}