Skip to main content

turbo_tasks/
read_ref.rs

1use std::{
2    cmp::Ordering,
3    fmt::{self, Debug, Display},
4    hash::{Hash, Hasher},
5    marker::PhantomData,
6    mem::transmute_copy,
7    ops::Deref,
8};
9
10use bincode::{
11    Decode, Encode,
12    de::Decoder,
13    enc::Encoder,
14    error::{DecodeError, EncodeError},
15    impl_borrow_decode_with_context,
16};
17use serde::{Deserialize, Serialize};
18use turbo_tasks_hash::DeterministicHash;
19
20use crate::{
21    SharedReference, Vc, VcRead, VcValueType,
22    debug::{ValueDebugFormat, ValueDebugFormatString},
23    trace::{TraceRawVcs, TraceRawVcsContext},
24    vc::VcCellMode,
25};
26
27type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
28
29/// The read value of a value cell. The read value is immutable, while the cell
30/// itself might change over time. It's basically a snapshot of a value at a
31/// certain point in time.
32///
33/// Internally it stores a reference counted reference to a value on the heap.
34pub struct ReadRef<T>(pub(crate) triomphe::Arc<T>);
35
36impl<T> Clone for ReadRef<T> {
37    fn clone(&self) -> Self {
38        Self(self.0.clone())
39    }
40}
41
42impl<T> Deref for ReadRef<T>
43where
44    T: VcValueType,
45{
46    type Target = VcReadTarget<T>;
47
48    fn deref(&self) -> &Self::Target {
49        T::Read::value_to_target_ref(&self.0)
50    }
51}
52
53impl<T> Display for ReadRef<T>
54where
55    T: VcValueType,
56    VcReadTarget<T>: Display,
57{
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        Display::fmt(&**self, f)
60    }
61}
62
63impl<T> Debug for ReadRef<T>
64where
65    T: Debug,
66{
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        Self::as_raw_ref(self).fmt(f)
69    }
70}
71
72impl<T> TraceRawVcs for ReadRef<T>
73where
74    T: TraceRawVcs,
75{
76    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
77        Self::as_raw_ref(self).trace_raw_vcs(trace_context);
78    }
79}
80
81impl<T> ValueDebugFormat for ReadRef<T>
82where
83    T: VcValueType,
84    VcReadTarget<T>: ValueDebugFormat + 'static,
85{
86    fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
87        let value = &**self;
88        value.value_debug_format(depth)
89    }
90}
91
92impl<T> PartialEq for ReadRef<T>
93where
94    T: PartialEq,
95{
96    fn eq(&self, other: &Self) -> bool {
97        Self::as_raw_ref(self).eq(Self::as_raw_ref(other))
98    }
99}
100
101impl<T> Eq for ReadRef<T> where T: Eq {}
102
103impl<T> PartialOrd for ReadRef<T>
104where
105    T: PartialOrd,
106{
107    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
108        Self::as_raw_ref(self).partial_cmp(Self::as_raw_ref(other))
109    }
110}
111
112impl<T> Ord for ReadRef<T>
113where
114    T: Ord,
115{
116    fn cmp(&self, other: &Self) -> Ordering {
117        Self::as_raw_ref(self).cmp(Self::as_raw_ref(other))
118    }
119}
120
121impl<T> Hash for ReadRef<T>
122where
123    T: Hash,
124{
125    fn hash<H: Hasher>(&self, state: &mut H) {
126        Self::as_raw_ref(self).hash(state)
127    }
128}
129
130impl<T> DeterministicHash for ReadRef<T>
131where
132    T: VcValueType,
133    VcReadTarget<T>: DeterministicHash,
134{
135    fn deterministic_hash<H: turbo_tasks_hash::DeterministicHasher>(&self, state: &mut H) {
136        let p = &**self;
137        p.deterministic_hash(state);
138    }
139}
140
141impl<'a, T, I, J: Iterator<Item = I>> IntoIterator for &'a ReadRef<T>
142where
143    T: VcValueType,
144    &'a VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
145{
146    type Item = I;
147
148    type IntoIter = J;
149
150    fn into_iter(self) -> Self::IntoIter {
151        (&**self).into_iter()
152    }
153}
154
155impl<T, I: 'static, J: Iterator<Item = I>> IntoIterator for ReadRef<T>
156where
157    T: VcValueType,
158    &'static VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
159{
160    type Item = I;
161
162    type IntoIter = ReadRefIter<T, I, J>;
163
164    fn into_iter(self) -> Self::IntoIter {
165        let r = &*self;
166        // # Safety
167        // The reference will we valid as long as the ReadRef is valid.
168        let r = unsafe { transmute_copy::<&'_ VcReadTarget<T>, &'static VcReadTarget<T>>(&r) };
169        ReadRefIter {
170            read_ref: self,
171            iter: r.into_iter(),
172        }
173    }
174}
175
176pub struct ReadRefIter<T, I: 'static, J: Iterator<Item = I>>
177where
178    T: VcValueType,
179{
180    iter: J,
181    #[allow(dead_code)]
182    read_ref: ReadRef<T>,
183}
184
185impl<T, I: 'static, J: Iterator<Item = I>> Iterator for ReadRefIter<T, I, J>
186where
187    T: VcValueType,
188{
189    type Item = I;
190
191    fn next(&mut self) -> Option<Self::Item> {
192        self.iter.next()
193    }
194}
195
196impl<T> Serialize for ReadRef<T>
197where
198    T: Serialize,
199{
200    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
201    where
202        S: serde::Serializer,
203    {
204        Self::as_raw_ref(self).serialize(serializer)
205    }
206}
207
208impl<'de, T> Deserialize<'de> for ReadRef<T>
209where
210    T: Deserialize<'de>,
211{
212    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
213    where
214        D: serde::Deserializer<'de>,
215    {
216        let value = T::deserialize(deserializer)?;
217        Ok(Self(triomphe::Arc::new(value)))
218    }
219}
220
221impl<T> Encode for ReadRef<T>
222where
223    T: Encode,
224{
225    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
226        Self::as_raw_ref(self).encode(encoder)
227    }
228}
229
230impl<Context, T> Decode<Context> for ReadRef<T>
231where
232    T: Decode<Context>,
233{
234    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
235        let value = T::decode(decoder)?;
236        Ok(Self(triomphe::Arc::new(value)))
237    }
238}
239
240impl_borrow_decode_with_context!(ReadRef<T>, Context, Context, T: Decode<Context>);
241
242impl<T> ReadRef<T> {
243    pub fn new_owned(value: T) -> Self {
244        Self(triomphe::Arc::new(value))
245    }
246
247    pub fn new_arc(arc: triomphe::Arc<T>) -> Self {
248        Self(arc)
249    }
250
251    /// Returns the reference to `&T`, rather than `<<T as VcValueType>::Read as VcRead<T>>::Target`
252    /// (the behavior of [`Deref`]).
253    pub fn as_raw_ref(this: &ReadRef<T>) -> &T {
254        &this.0
255    }
256
257    /// Returns the inner `Arc<T>`.
258    pub fn into_raw_arc(self) -> triomphe::Arc<T> {
259        self.0
260    }
261
262    pub fn ptr_eq(&self, other: &ReadRef<T>) -> bool {
263        triomphe::Arc::ptr_eq(&self.0, &other.0)
264    }
265
266    pub fn ptr(&self) -> *const T {
267        &*self.0 as *const T
268    }
269}
270
271impl<T> ReadRef<T>
272where
273    T: VcValueType,
274{
275    /// Returns a new cell that points to the same value as the given
276    /// reference.
277    pub fn cell(read_ref: ReadRef<T>) -> Vc<T> {
278        let type_id = T::get_value_type_id();
279        Vc {
280            node: <T::CellMode as VcCellMode<T>>::raw_cell(
281                SharedReference::new(read_ref.0).into_typed(type_id),
282            ),
283            _t: PhantomData,
284        }
285    }
286}
287
288impl<T> ReadRef<T>
289where
290    T: VcValueType,
291{
292    /// Returns the inner value, if this [`ReadRef`] has exactly one strong reference.
293    ///
294    /// Otherwise, an [`Err`] is returned with the same [`ReadRef`] that was passed in.
295    pub fn try_unwrap(this: Self) -> Result<VcReadTarget<T>, Self> {
296        match triomphe::Arc::try_unwrap(this.0) {
297            Ok(value) => Ok(T::Read::value_to_target(value)),
298            Err(arc) => Err(Self(arc)),
299        }
300    }
301}
302
303impl<T> ReadRef<T>
304where
305    T: VcValueType,
306    VcReadTarget<T>: Clone,
307{
308    /// This is return a owned version of the value. It potentially clones the value.
309    /// The clone might be expensive. Prefer Deref to get a reference to the value.
310    pub fn into_owned(this: Self) -> VcReadTarget<T> {
311        Self::try_unwrap(this).unwrap_or_else(|this| (*this).clone())
312    }
313}