Skip to main content

blazingly_json/
raw_value.rs

1#![allow(unsafe_code)]
2
3//! The only unsafe code in `blazingly-json`.
4//!
5//! `RawValue` is a transparent dynamically sized wrapper around `str`. The
6//! three conversions below preserve the data pointer and slice metadata
7//! exactly. No bytes are read through a different layout, and owned
8//! conversions preserve the original allocation and allocator.
9
10use crate::{from_str, to_string, Error, Result};
11use serde::de::{self, DeserializeSeed, MapAccess, Unexpected, Visitor};
12use serde::ser::{SerializeStruct, Serializer};
13use serde::{Deserialize, Serialize};
14use std::fmt;
15use std::io::{self, Write};
16use std::mem;
17
18/// Serde's established private representation for a verbatim JSON value.
19///
20/// Using the same token makes this type interoperable with `serde_json`
21/// serializers and deserializers that support `RawValue`.
22pub(crate) const RAW_VALUE_TOKEN: &str = "$serde_json::private::RawValue";
23
24/// A reference to one complete, validated JSON value.
25///
26/// Borrowed values point directly into the input buffer. Serializing a
27/// `RawValue` writes its original representation verbatim, including internal
28/// whitespace.
29#[repr(transparent)]
30pub struct RawValue {
31    json: str,
32}
33
34impl RawValue {
35    /// A raw JSON `null`.
36    pub const NULL: &'static Self = Self::from_borrowed("null");
37
38    /// A raw JSON `true`.
39    pub const TRUE: &'static Self = Self::from_borrowed("true");
40
41    /// A raw JSON `false`.
42    pub const FALSE: &'static Self = Self::from_borrowed("false");
43
44    #[inline]
45    const fn from_borrowed(json: &str) -> &Self {
46        // SAFETY: RawValue is repr(transparent) over its only field, `str`.
47        // Therefore &str and &RawValue have identical data and metadata.
48        unsafe { mem::transmute::<&str, &Self>(json) }
49    }
50
51    #[inline]
52    fn from_owned(json: Box<str>) -> Box<Self> {
53        // SAFETY: RawValue is repr(transparent) over `str`. Box preserves the
54        // same allocation, length metadata, alignment, and allocator.
55        unsafe { mem::transmute::<Box<str>, Box<Self>>(json) }
56    }
57
58    #[inline]
59    fn into_owned(raw: Box<Self>) -> Box<str> {
60        // SAFETY: This is the exact inverse of from_owned and restores the
61        // original Box<str> representation and deallocation layout.
62        unsafe { mem::transmute::<Box<Self>, Box<str>>(raw) }
63    }
64
65    /// Validates an owned JSON string and converts it into a boxed raw value.
66    ///
67    /// When the input has no surrounding whitespace this reuses its allocation.
68    /// Otherwise only the validated JSON value is copied.
69    ///
70    /// # Errors
71    ///
72    /// Returns an error unless the string contains exactly one valid JSON
73    /// value, optionally surrounded by whitespace.
74    pub fn from_string(json: String) -> Result<Box<Self>> {
75        let borrowed = from_str::<&Self>(&json)?;
76        if borrowed.get().len() != json.len() {
77            return Ok(borrowed.to_owned());
78        }
79        Ok(Self::from_owned(json.into_boxed_str()))
80    }
81
82    /// Converts an owned JSON string without validating it.
83    ///
84    /// # Safety
85    ///
86    /// `json` must contain exactly one well-formed JSON value with no leading
87    /// or trailing whitespace. Raw values are emitted verbatim, so violating
88    /// this invariant can make subsequent serializer output invalid.
89    #[must_use]
90    pub unsafe fn from_string_unchecked(json: String) -> Box<Self> {
91        debug_assert!(
92            from_str::<&Self>(&json).is_ok_and(|raw| raw.get().len() == json.len()),
93            "RawValue::from_string_unchecked requires one valid JSON value without surrounding whitespace",
94        );
95        Self::from_owned(json.into_boxed_str())
96    }
97
98    /// Returns the exact JSON representation.
99    #[must_use]
100    #[inline]
101    pub fn get(&self) -> &str {
102        &self.json
103    }
104
105    /// Copies the raw JSON bytes directly into an exactly sized vector.
106    ///
107    /// This bypasses the generic Serde marker protocol when the raw value is
108    /// the complete output document.
109    #[must_use]
110    #[inline]
111    pub fn to_vec(&self) -> Vec<u8> {
112        self.json.as_bytes().to_vec()
113    }
114
115    /// Writes the raw JSON bytes directly to a writer.
116    ///
117    /// Use generic serialization instead when embedding this value inside a
118    /// larger structure.
119    ///
120    /// # Errors
121    ///
122    /// Returns any error produced by `writer`.
123    #[inline]
124    pub fn write_to<W: Write>(&self, mut writer: W) -> io::Result<()> {
125        writer.write_all(self.json.as_bytes())
126    }
127
128    /// Converts a boxed raw value back into a string while reusing its
129    /// allocation.
130    #[must_use]
131    #[inline]
132    pub fn into_string(self: Box<Self>) -> String {
133        String::from(Self::into_owned(self))
134    }
135}
136
137impl Clone for Box<RawValue> {
138    #[inline]
139    fn clone(&self) -> Self {
140        (**self).to_owned()
141    }
142}
143
144impl ToOwned for RawValue {
145    type Owned = Box<Self>;
146
147    #[inline]
148    fn to_owned(&self) -> Self::Owned {
149        RawValue::from_owned(self.json.to_owned().into_boxed_str())
150    }
151}
152
153impl Default for Box<RawValue> {
154    #[inline]
155    fn default() -> Self {
156        RawValue::NULL.to_owned()
157    }
158}
159
160impl fmt::Debug for RawValue {
161    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
162        formatter
163            .debug_tuple("RawValue")
164            .field(&format_args!("{}", &self.json))
165            .finish()
166    }
167}
168
169impl fmt::Display for RawValue {
170    #[inline]
171    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
172        formatter.write_str(&self.json)
173    }
174}
175
176impl From<Box<RawValue>> for Box<str> {
177    #[inline]
178    fn from(raw: Box<RawValue>) -> Self {
179        RawValue::into_owned(raw)
180    }
181}
182
183/// Serializes a value once and retains the resulting JSON verbatim.
184///
185/// # Errors
186///
187/// Returns an error if `value` cannot be represented as JSON.
188pub fn to_raw_value<T>(value: &T) -> Result<Box<RawValue>>
189where
190    T: Serialize + ?Sized,
191{
192    let json = to_string(value)?;
193    Ok(RawValue::from_owned(json.into_boxed_str()))
194}
195
196impl Serialize for RawValue {
197    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
198    where
199        S: Serializer,
200    {
201        let mut raw = serializer.serialize_struct(RAW_VALUE_TOKEN, 1)?;
202        raw.serialize_field(RAW_VALUE_TOKEN, &self.json)?;
203        raw.end()
204    }
205}
206
207struct RawKey;
208
209impl<'de> Deserialize<'de> for RawKey {
210    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
211    where
212        D: de::Deserializer<'de>,
213    {
214        struct RawKeyVisitor;
215
216        impl Visitor<'_> for RawKeyVisitor {
217            type Value = ();
218
219            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
220                formatter.write_str("the RawValue marker")
221            }
222
223            fn visit_str<E>(self, value: &str) -> std::result::Result<(), E>
224            where
225                E: de::Error,
226            {
227                if value == RAW_VALUE_TOKEN {
228                    Ok(())
229                } else {
230                    Err(E::custom("unexpected raw value marker"))
231                }
232            }
233        }
234
235        deserializer.deserialize_identifier(RawKeyVisitor)?;
236        Ok(Self)
237    }
238}
239
240struct BorrowedRawSeed;
241
242impl<'de> DeserializeSeed<'de> for BorrowedRawSeed {
243    type Value = &'de RawValue;
244
245    fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
246    where
247        D: de::Deserializer<'de>,
248    {
249        deserializer.deserialize_str(self)
250    }
251}
252
253impl<'de> Visitor<'de> for BorrowedRawSeed {
254    type Value = &'de RawValue;
255
256    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
257        formatter.write_str("a borrowed raw JSON value")
258    }
259
260    #[inline]
261    fn visit_borrowed_str<E>(self, value: &'de str) -> std::result::Result<Self::Value, E>
262    where
263        E: de::Error,
264    {
265        Ok(RawValue::from_borrowed(value))
266    }
267}
268
269struct BoxedRawSeed;
270
271impl<'de> DeserializeSeed<'de> for BoxedRawSeed {
272    type Value = Box<RawValue>;
273
274    fn deserialize<D>(self, deserializer: D) -> std::result::Result<Self::Value, D::Error>
275    where
276        D: de::Deserializer<'de>,
277    {
278        deserializer.deserialize_str(self)
279    }
280}
281
282impl Visitor<'_> for BoxedRawSeed {
283    type Value = Box<RawValue>;
284
285    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
286        formatter.write_str("an owned raw JSON value")
287    }
288
289    #[inline]
290    fn visit_str<E>(self, value: &str) -> std::result::Result<Self::Value, E>
291    where
292        E: de::Error,
293    {
294        Ok(RawValue::from_owned(value.to_owned().into_boxed_str()))
295    }
296
297    #[inline]
298    fn visit_string<E>(self, value: String) -> std::result::Result<Self::Value, E>
299    where
300        E: de::Error,
301    {
302        Ok(RawValue::from_owned(value.into_boxed_str()))
303    }
304}
305
306struct BorrowedRawVisitor;
307
308impl<'de> Visitor<'de> for BorrowedRawVisitor {
309    type Value = &'de RawValue;
310
311    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
312        formatter.write_str("any valid JSON value")
313    }
314
315    fn visit_map<A>(self, mut map: A) -> std::result::Result<Self::Value, A::Error>
316    where
317        A: MapAccess<'de>,
318    {
319        if map.next_key::<RawKey>()?.is_none() {
320            return Err(de::Error::invalid_type(Unexpected::Map, &self));
321        }
322        map.next_value_seed(BorrowedRawSeed)
323    }
324}
325
326struct BoxedRawVisitor;
327
328impl<'de> Visitor<'de> for BoxedRawVisitor {
329    type Value = Box<RawValue>;
330
331    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
332        formatter.write_str("any valid JSON value")
333    }
334
335    fn visit_map<A>(self, mut map: A) -> std::result::Result<Self::Value, A::Error>
336    where
337        A: MapAccess<'de>,
338    {
339        if map.next_key::<RawKey>()?.is_none() {
340            return Err(de::Error::invalid_type(Unexpected::Map, &self));
341        }
342        map.next_value_seed(BoxedRawSeed)
343    }
344}
345
346impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
347    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
348    where
349        D: de::Deserializer<'de>,
350    {
351        deserializer.deserialize_newtype_struct(RAW_VALUE_TOKEN, BorrowedRawVisitor)
352    }
353}
354
355impl<'de> Deserialize<'de> for Box<RawValue> {
356    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
357    where
358        D: de::Deserializer<'de>,
359    {
360        deserializer.deserialize_newtype_struct(RAW_VALUE_TOKEN, BoxedRawVisitor)
361    }
362}
363
364impl<'de> de::IntoDeserializer<'de, Error> for &'de RawValue {
365    type Deserializer = &'de RawValue;
366
367    #[inline]
368    fn into_deserializer(self) -> Self::Deserializer {
369        self
370    }
371}
372
373macro_rules! forward_raw_visitor {
374    ($($method:ident),+ $(,)?) => {
375        $(
376            fn $method<V>(self, visitor: V) -> Result<V::Value>
377            where
378                V: Visitor<'de>,
379            {
380                let mut deserializer = crate::Deserializer::from_str(self.get());
381                de::Deserializer::$method(&mut deserializer, visitor)
382            }
383        )+
384    };
385}
386
387impl<'de> de::Deserializer<'de> for &'de RawValue {
388    type Error = Error;
389
390    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
391    where
392        V: Visitor<'de>,
393    {
394        let mut deserializer = crate::Deserializer::from_str(self.get());
395        de::Deserializer::deserialize_any(&mut deserializer, visitor)
396    }
397
398    forward_raw_visitor! {
399        deserialize_bool,
400        deserialize_i8,
401        deserialize_i16,
402        deserialize_i32,
403        deserialize_i64,
404        deserialize_i128,
405        deserialize_u8,
406        deserialize_u16,
407        deserialize_u32,
408        deserialize_u64,
409        deserialize_u128,
410        deserialize_f32,
411        deserialize_f64,
412        deserialize_char,
413        deserialize_str,
414        deserialize_string,
415        deserialize_bytes,
416        deserialize_byte_buf,
417        deserialize_option,
418        deserialize_unit,
419        deserialize_seq,
420        deserialize_map,
421        deserialize_identifier,
422        deserialize_ignored_any
423    }
424
425    fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
426    where
427        V: Visitor<'de>,
428    {
429        let mut deserializer = crate::Deserializer::from_str(self.get());
430        de::Deserializer::deserialize_unit_struct(&mut deserializer, name, visitor)
431    }
432
433    fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
434    where
435        V: Visitor<'de>,
436    {
437        let mut deserializer = crate::Deserializer::from_str(self.get());
438        de::Deserializer::deserialize_newtype_struct(&mut deserializer, name, visitor)
439    }
440
441    fn deserialize_tuple<V>(self, length: usize, visitor: V) -> Result<V::Value>
442    where
443        V: Visitor<'de>,
444    {
445        let mut deserializer = crate::Deserializer::from_str(self.get());
446        de::Deserializer::deserialize_tuple(&mut deserializer, length, visitor)
447    }
448
449    fn deserialize_tuple_struct<V>(
450        self,
451        name: &'static str,
452        length: usize,
453        visitor: V,
454    ) -> Result<V::Value>
455    where
456        V: Visitor<'de>,
457    {
458        let mut deserializer = crate::Deserializer::from_str(self.get());
459        de::Deserializer::deserialize_tuple_struct(&mut deserializer, name, length, visitor)
460    }
461
462    fn deserialize_struct<V>(
463        self,
464        name: &'static str,
465        fields: &'static [&'static str],
466        visitor: V,
467    ) -> Result<V::Value>
468    where
469        V: Visitor<'de>,
470    {
471        let mut deserializer = crate::Deserializer::from_str(self.get());
472        de::Deserializer::deserialize_struct(&mut deserializer, name, fields, visitor)
473    }
474
475    fn deserialize_enum<V>(
476        self,
477        name: &'static str,
478        variants: &'static [&'static str],
479        visitor: V,
480    ) -> Result<V::Value>
481    where
482        V: Visitor<'de>,
483    {
484        let mut deserializer = crate::Deserializer::from_str(self.get());
485        de::Deserializer::deserialize_enum(&mut deserializer, name, variants, visitor)
486    }
487}