abi_stable/external_types/
serde_json.rs

1//! Ffi-safe equivalents of `serde_json` types.
2
3use std::{
4    convert::{TryFrom, TryInto},
5    fmt::{self, Debug, Display},
6};
7
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9use serde_json::{error::Error as JsonError, value::RawValue};
10
11use crate::std_types::{RStr, RString};
12
13/// An ffi-safe equivalent of `&serde_json::value::RawValue`
14///
15/// # Example
16///
17/// This defines a function that serializes a struct,
18/// and deserializes the json into another one with `RawValueRef` fields.
19///
20/// ```
21/// use abi_stable::{
22///     external_types::RawValueRef,
23///     sabi_extern_fn,
24///     std_types::{RBoxError, RErr, ROk, RResult, RStr, RString},
25/// };
26///
27/// use serde::{Deserialize, Serialize};
28///
29/// use std::collections::HashMap;
30///
31/// const JSON: &'static str = r##"{"hello":"world"}"##;
32///
33/// let value = RawValueRef::try_from_str(JSON).unwrap();
34///
35/// assert_eq!(serde_json::to_string(&value).unwrap().as_str(), JSON);
36///
37/// #[derive(Serialize)]
38/// pub struct Pair {
39///     pub first: Vec<u32>,
40///     pub second: HashMap<RString, RString>,
41/// }
42///
43/// #[derive(Debug, Deserialize)]
44/// pub struct PairDeserialize<'a> {
45///     #[serde(borrow)]
46///     pub first: RawValueRef<'a>,
47///
48///     #[serde(borrow)]
49///     pub second: RawValueRef<'a>,
50/// }
51///
52/// #[sabi_extern_fn]
53/// fn deserialize_data_structure<'de>(
54///     input: RStr<'de>,
55/// ) -> RResult<PairDeserialize<'de>, RBoxError> {
56///     match serde_json::from_str::<PairDeserialize>(input.into()) {
57///         Ok(x) => ROk(x),
58///         Err(x) => RErr(RBoxError::new(x)),
59///     }
60/// }
61///
62/// # fn main(){
63///
64/// let json = serde_json::to_string(&Pair {
65///     first: vec![0, 1, 2],
66///     second: vec![(RString::from("hello"), "world".into())]
67///         .into_iter()
68///         .collect(),
69/// })
70/// .unwrap();
71///
72/// let pair = deserialize_data_structure(json.as_str().into()).unwrap();
73///
74/// assert_eq!(pair.first.get(), "[0,1,2]");
75/// assert_eq!(pair.second.get(), r##"{"hello":"world"}"##);
76///
77/// # }
78///
79/// ```
80#[repr(transparent)]
81#[derive(StableAbi, Copy, Clone)]
82pub struct RawValueRef<'a> {
83    ref_: RStr<'a>,
84}
85
86impl<'a> RawValueRef<'a> {
87    /// Converts a `&str` to a `RawValueRef<'a>` without checking whether it is valid JSON.
88    ///
89    /// # Safety
90    ///
91    /// `input` must be valid JSON and contain no leading or trailing whitespace.
92    ///
93    /// # Example
94    ///
95    /// ```
96    /// use abi_stable::external_types::RawValueRef;
97    ///
98    /// const JSON: &'static str = r##"{"huh":"that is interesting"}"##;
99    ///
100    /// const VALUE: RawValueRef<'_> = unsafe { RawValueRef::from_str_unchecked(JSON) };
101    ///
102    /// assert_eq!(serde_json::to_string(&VALUE).unwrap().as_str(), JSON);
103    ///
104    /// ```
105    pub const unsafe fn from_str_unchecked(input: &'a str) -> RawValueRef<'a> {
106        Self {
107            ref_: RStr::from_str(input),
108        }
109    }
110
111    /// Converts a `RStr<'a>` to a `RawValueRef<'a>` without checking whether it is valid JSON.
112    ///
113    /// # Safety
114    ///
115    /// `input` must be valid JSON and contain no leading or trailing whitespace.
116    ///
117    ///
118    /// # Example
119    ///
120    /// ```
121    /// use abi_stable::{external_types::RawValueRef, std_types::RStr};
122    ///
123    /// const JSON: &'static str = r##"{"huh":"that is interesting"}"##;
124    ///
125    /// let json_rstr = RStr::from(JSON);
126    /// let value = unsafe { RawValueRef::from_rstr_unchecked(json_rstr) };
127    ///
128    /// assert_eq!(serde_json::to_string(&value).unwrap().as_str(), JSON);
129    /// ```
130    ///
131    ///
132    pub const unsafe fn from_rstr_unchecked(input: RStr<'a>) -> RawValueRef<'a> {
133        Self { ref_: input }
134    }
135
136    /// Attempts to convert a `&'a str` into a `RawValueRef<'a>`.
137    ///
138    /// Fails in the same cases as parsing a `&'a RawValue` from a string does.
139    ///
140    /// # Example
141    ///
142    /// ```
143    /// use abi_stable::{external_types::RawValueRef, std_types::RStr};
144    ///
145    /// const JSON: &'static str = r##"{"nope":"oof"}"##;
146    ///
147    /// let raw = RawValueRef::try_from_str(JSON).unwrap();
148    ///
149    /// assert_eq!(raw.get(), JSON);
150    ///
151    /// ```
152    #[inline]
153    pub fn try_from_str(input: &'a str) -> Result<Self, JsonError> {
154        input.try_into()
155    }
156
157    /// Gets the json being serialized,as a `&str`.
158    ///
159    /// # Example
160    ///
161    /// ```
162    /// use abi_stable::external_types::RawValueRef;
163    ///
164    /// const JSON: &'static str = r##"{"huh":1007}"##;
165    ///
166    /// let raw = serde_json::from_str::<RawValueRef<'static>>(JSON).unwrap();
167    ///
168    /// assert_eq!(raw.get(), JSON);
169    ///
170    /// ```
171    #[inline]
172    pub fn get(&self) -> &'a str {
173        self.ref_.as_str()
174    }
175
176    /// Gets the json being serialized,as a `RStr<'a>`.
177    ///
178    /// # Example
179    ///
180    /// ```
181    /// use abi_stable::{external_types::RawValueRef, std_types::RStr};
182    ///
183    /// const JSON: &'static str = r##"{"bugs":"life"}"##;
184    ///
185    /// let raw = serde_json::from_str::<RawValueRef<'static>>(JSON).unwrap();
186    ///
187    /// assert_eq!(raw.get_rstr(), RStr::from(JSON));
188    ///
189    /// ```
190    #[inline]
191    pub const fn get_rstr(&self) -> RStr<'a> {
192        self.ref_
193    }
194}
195
196impl<'a> Debug for RawValueRef<'a> {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        Debug::fmt(&self.ref_, f)
199    }
200}
201
202impl<'a> Display for RawValueRef<'a> {
203    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204        Display::fmt(&self.ref_, f)
205    }
206}
207
208impl<'a> From<&'a RawValue> for RawValueRef<'a> {
209    fn from(v: &'a RawValue) -> Self {
210        Self {
211            ref_: v.get().into(),
212        }
213    }
214}
215
216impl<'a> TryFrom<&'a str> for RawValueRef<'a> {
217    type Error = JsonError;
218    fn try_from(v: &'a str) -> Result<Self, JsonError> {
219        serde_json::from_str::<&'a RawValue>(v).map(Self::from)
220    }
221}
222
223impl<'a> Serialize for RawValueRef<'a> {
224    fn serialize<Z>(&self, serializer: Z) -> Result<Z::Ok, Z::Error>
225    where
226        Z: Serializer,
227    {
228        unsafe { into_ref_rawvalue(self.ref_.as_str()).serialize(serializer) }
229    }
230}
231
232impl<'de: 'a, 'a> Deserialize<'de> for RawValueRef<'a> {
233    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
234    where
235        D: Deserializer<'de>,
236    {
237        <&'a RawValue>::deserialize(deserializer).map(Self::from)
238    }
239}
240
241///////////////////////////////////////////////////////////////////////////////
242
243/// An ffi-safe equivalent of `Box<serde_json::value::RawValue>`
244///
245///
246/// # Example
247///
248/// This defines a function that serializes a struct,
249/// and deserializes the json into another one with `RawValueBox` fields.
250///
251/// ```
252/// use abi_stable::{
253///     external_types::RawValueBox,
254///     sabi_extern_fn,
255///     std_types::{RBoxError, RErr, ROk, RResult, RStr, RString},
256/// };
257///
258/// use serde::{Deserialize, Serialize};
259///
260/// const JSON: &'static str = r##"{"hello":"world"}"##;
261///
262/// let value = RawValueBox::try_from_string(JSON.to_string()).unwrap();
263///
264/// assert_eq!(serde_json::to_string(&value).unwrap().as_str(), JSON);
265///
266/// #[derive(Serialize)]
267/// pub struct Pair {
268///     pub first: u64,
269///     pub second: RString,
270/// }
271///
272/// #[derive(Debug, Deserialize)]
273/// pub struct PairDeserialize {
274///     pub first: RawValueBox,
275///     pub second: RawValueBox,
276/// }
277///
278/// #[sabi_extern_fn]
279/// fn deserialize_data_structure(
280///     input: RStr<'_>,
281/// ) -> RResult<PairDeserialize, RBoxError> {
282///     match serde_json::from_str::<PairDeserialize>(input.into()) {
283///         Ok(x) => ROk(x),
284///         Err(x) => RErr(RBoxError::new(x)),
285///     }
286/// }
287///
288/// # fn main(){
289///
290/// let json = serde_json::to_string(&Pair {
291///     first: 99,
292///     second: "How many apples?".into(),
293/// })
294/// .unwrap();
295///
296/// let pair = deserialize_data_structure(json.as_str().into()).unwrap();
297///
298/// assert_eq!(pair.first.get(), "99");
299/// assert_eq!(pair.second.get(), r##""How many apples?"}"##);
300///
301/// # }
302///
303///
304/// ```
305///
306#[repr(transparent)]
307#[derive(StableAbi, Clone)]
308pub struct RawValueBox {
309    string: RString,
310}
311
312impl RawValueBox {
313    /// Converts a `String` to an `RawValueBox` without checking whether it is valid JSON.
314    ///
315    /// # Safety
316    ///
317    /// `input` must be valid JSON and contain no leading or trailing whitespace.
318    ///
319    ///
320    /// # Example
321    ///
322    /// ```
323    /// use abi_stable::external_types::RawValueBox;
324    ///
325    /// const JSON: &'static str = r##"{"huh":"that is interesting"}"##;
326    ///
327    /// let value = unsafe { RawValueBox::from_string_unchecked(JSON.to_string()) };
328    ///
329    /// assert_eq!(serde_json::to_string(&value).unwrap().as_str(), JSON);
330    /// ```
331    ///
332    #[inline]
333    pub unsafe fn from_string_unchecked(input: String) -> RawValueBox {
334        Self {
335            string: input.into(),
336        }
337    }
338
339    /// Converts an `RString` to an `RawValueBox` without checking whether it is valid JSON.
340    ///
341    /// # Safety
342    ///
343    /// `input` must be valid JSON and contain no leading or trailing whitespace.
344    ///
345    ///
346    /// # Example
347    ///
348    /// ```
349    /// use abi_stable::{external_types::RawValueBox, std_types::RString};
350    ///
351    /// const JSON: &'static str = r##"{"huh":"that is interesting"}"##;
352    ///
353    /// let json_rstring = RString::from(JSON);
354    /// let value = unsafe { RawValueBox::from_rstring_unchecked(json_rstring) };
355    ///
356    /// assert_eq!(serde_json::to_string(&value).unwrap().as_str(), JSON);
357    /// ```
358    ///
359    #[inline]
360    pub const unsafe fn from_rstring_unchecked(input: RString) -> RawValueBox {
361        Self { string: input }
362    }
363
364    /// Attempts to convert a `String` into a `RawValueBox`.
365    ///
366    /// Fails in the same cases as converting a String into a `Box<RawValue>` does.
367    ///
368    /// # Example
369    ///
370    /// ```
371    /// use abi_stable::{external_types::RawValueBox, std_types::RString};
372    ///
373    /// const JSON: &'static str = r##"{"nope":"oof"}"##;
374    ///
375    /// let raw = RawValueBox::try_from_string(JSON.to_string()).unwrap();
376    ///
377    /// assert_eq!(raw.get(), JSON);
378    ///
379    /// ```
380    #[inline]
381    pub fn try_from_string(input: String) -> Result<Self, JsonError> {
382        input.try_into()
383    }
384
385    /// Gets the json being serialized,as a `&str`.
386    ///
387    /// # Example
388    ///
389    /// ```
390    /// use abi_stable::external_types::RawValueBox;
391    ///
392    /// const JSON: &'static str = r##"{"huh":1007}"##;
393    ///
394    /// let raw = serde_json::from_str::<RawValueBox>(JSON).unwrap();
395    ///
396    /// assert_eq!(raw.get(), JSON);
397    ///
398    /// ```
399    #[inline]
400    pub fn get(&self) -> &str {
401        self.string.as_str()
402    }
403
404    /// Gets the json being serialized,as a `RStr<'a>`.
405    ///
406    /// # Example
407    ///
408    /// ```
409    /// use abi_stable::{external_types::RawValueBox, std_types::RStr};
410    ///
411    /// const JSON: &'static str = r##"{"bugs":"life"}"##;
412    ///
413    /// let raw = serde_json::from_str::<RawValueBox>(JSON).unwrap();
414    ///
415    /// assert_eq!(raw.get_rstr(), RStr::from(JSON));
416    ///
417    /// ```
418    #[inline]
419    pub fn get_rstr(&self) -> RStr<'_> {
420        self.get().into()
421    }
422
423    /// Gets a RawValueRef<'_> borrowing from this RawValueBox.
424    ///
425    /// # Example
426    ///
427    /// ```
428    /// use abi_stable::external_types::{RawValueBox, RawValueRef};
429    ///
430    /// const JSON: &'static str = r##"{"bugs":"life"}"##;
431    ///
432    /// let raw = serde_json::from_str::<RawValueBox>(JSON).unwrap();
433    ///
434    /// assert_eq!(raw.get(), RawValueRef::try_from_str(JSON).unwrap().get());
435    ///
436    /// ```
437    #[inline]
438    pub fn as_raw_value_ref(&self) -> RawValueRef<'_> {
439        unsafe { RawValueRef::from_str_unchecked(self.get()) }
440    }
441}
442
443impl Debug for RawValueBox {
444    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445        Debug::fmt(&self.string, f)
446    }
447}
448
449impl Display for RawValueBox {
450    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451        Display::fmt(&self.string, f)
452    }
453}
454
455impl From<Box<RawValue>> for RawValueBox {
456    fn from(v: Box<RawValue>) -> Self {
457        let string: String = from_boxed_rawvalue(v).into();
458        Self {
459            string: string.into(),
460        }
461    }
462}
463
464impl TryFrom<String> for RawValueBox {
465    type Error = JsonError;
466    fn try_from(v: String) -> Result<Self, JsonError> {
467        RawValue::from_string(v).map(Self::from)
468    }
469}
470
471impl Serialize for RawValueBox {
472    fn serialize<Z>(&self, serializer: Z) -> Result<Z::Ok, Z::Error>
473    where
474        Z: Serializer,
475    {
476        unsafe { into_ref_rawvalue(&self.string).serialize(serializer) }
477    }
478}
479
480impl<'de> Deserialize<'de> for RawValueBox {
481    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
482    where
483        D: Deserializer<'de>,
484    {
485        <Box<RawValue>>::deserialize(deserializer).map(Self::from)
486    }
487}
488
489///////////////////////////////////////////////////////////////////////////////
490
491fn from_boxed_rawvalue(x: Box<RawValue>) -> Box<str> {
492    // This would become Undefined Behavior if
493    // serde_json somehow changes RawValue to not be a transparent wrapper around `str`
494    unsafe { Box::from_raw(Box::into_raw(x) as *mut str) }
495}
496
497const unsafe fn into_ref_rawvalue(x: &str) -> &RawValue {
498    // This would become Undefined Behavior if
499    // serde_json somehow changes RawValue to not be a transparent wrapper around `str`
500    unsafe { &*(x as *const str as *const RawValue) }
501}