Skip to main content

turbopack_core/
json.rs

1use std::{
2    hash::{Hash, Hasher},
3    ops::Deref,
4    sync::Arc,
5};
6
7use bincode::{
8    Decode, Encode,
9    de::Decoder,
10    enc::Encoder,
11    error::{DecodeError, EncodeError},
12    impl_borrow_decode,
13};
14use serde::Serialize;
15use serde_json::value::RawValue;
16use turbo_tasks::TaskInput;
17
18/// A reference-counted [`RawValue`]: a string that is guaranteed to contain valid JSON.
19///
20/// This lets JSON produced in one task be passed through other tasks and re-emitted verbatim
21/// without re-validating it.
22///
23/// Values restored from the persistent cache are trusted to be valid JSON, like all other cached
24/// data.
25#[turbo_tasks::value(shared, serialization = "custom", eq = "manual")]
26#[derive(Clone, Debug)]
27pub struct RcJsonRawValue(#[turbo_tasks(debug_ignore, unsafe_ignore)] Arc<RawValue>);
28
29impl RcJsonRawValue {
30    pub fn from_serialize<T: Serialize + ?Sized>(value: &T) -> serde_json::Result<Self> {
31        Ok(Self(serde_json::value::to_raw_value(value)?.into()))
32    }
33}
34
35impl Deref for RcJsonRawValue {
36    type Target = RawValue;
37
38    fn deref(&self) -> &RawValue {
39        &self.0
40    }
41}
42
43impl PartialEq for RcJsonRawValue {
44    fn eq(&self, other: &Self) -> bool {
45        Arc::ptr_eq(&self.0, &other.0) || self.0.get() == other.0.get()
46    }
47}
48
49impl Eq for RcJsonRawValue {}
50
51impl Hash for RcJsonRawValue {
52    fn hash<H: Hasher>(&self, state: &mut H) {
53        self.0.get().hash(state);
54    }
55}
56
57impl TaskInput for RcJsonRawValue {
58    fn is_transient(&self) -> bool {
59        false
60    }
61}
62
63impl Encode for RcJsonRawValue {
64    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
65        self.0.get().encode(encoder)
66    }
67}
68
69impl<Context> Decode<Context> for RcJsonRawValue {
70    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
71        let json = String::decode(decoder)?;
72        // SAFETY: This was encoded from an `RcJsonRawValue`, which always holds valid JSON. Like
73        // all other persistent cache data, the encoded bytes are trusted.
74        Ok(Self(
75            unsafe { RawValue::from_string_unchecked(json) }.into(),
76        ))
77    }
78}
79
80impl_borrow_decode!(RcJsonRawValue);