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