Skip to main content

blazingly_json/
raw.rs

1use crate::{from_str, Result};
2use serde::de::{Deserializer, Visitor};
3use serde::Deserialize;
4use std::fmt;
5use std::marker::PhantomData;
6
7pub(crate) const RAW_JSON_TOKEN: &str = "$blazingly_json::RawJson";
8
9/// A validated JSON value borrowed directly from the input buffer.
10///
11/// `RawJson` is useful for protocol envelopes that need to inspect a few
12/// fields while deferring or avoiding deserialization of a large payload.
13/// Capturing it performs no allocation and preserves the exact compact or
14/// pretty representation from the input.
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct RawJson<'a> {
17    json: &'a str,
18}
19
20impl<'a> RawJson<'a> {
21    pub(crate) const fn new(json: &'a str) -> Self {
22        Self { json }
23    }
24
25    /// Returns the original JSON representation of this value.
26    #[must_use]
27    pub const fn get(self) -> &'a str {
28        self.json
29    }
30
31    /// Deserializes the captured value only when the caller needs it.
32    ///
33    /// # Errors
34    ///
35    /// Returns an error when the JSON does not match `T`.
36    pub fn deserialize<T>(self) -> Result<T>
37    where
38        T: Deserialize<'a>,
39    {
40        from_str(self.json)
41    }
42}
43
44struct RawJsonVisitor<'a>(PhantomData<&'a str>);
45
46impl<'de: 'a, 'a> Visitor<'de> for RawJsonVisitor<'a> {
47    type Value = RawJson<'a>;
48
49    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
50        formatter.write_str("a borrowed raw JSON value")
51    }
52
53    fn visit_borrowed_str<E>(self, value: &'de str) -> std::result::Result<Self::Value, E> {
54        Ok(RawJson::new(value))
55    }
56}
57
58impl<'de: 'a, 'a> Deserialize<'de> for RawJson<'a> {
59    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
60    where
61        D: Deserializer<'de>,
62    {
63        deserializer.deserialize_newtype_struct(RAW_JSON_TOKEN, RawJsonVisitor(PhantomData))
64    }
65}