Skip to main content

conjure_serde/json/
ser.rs

1// Copyright 2018 Palantir Technologies, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14use crate::ser::Behavior;
15use base64::display::Base64Display;
16use base64::engine::general_purpose::STANDARD;
17use serde::ser;
18use serde_json::ser::{CompactFormatter, Formatter, PrettyFormatter};
19use serde_json::Error;
20use std::f32;
21use std::f64;
22use std::io::Write;
23
24/// Serializes a value as JSON into a byte buffer.
25pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, Error>
26where
27    T: ?Sized + ser::Serialize,
28{
29    let mut buf = Vec::with_capacity(128);
30    value.serialize(&mut Serializer::new(&mut buf))?;
31    Ok(buf)
32}
33
34/// Serializes a value as JSON into a string.
35pub fn to_string<T>(value: &T) -> Result<String, Error>
36where
37    T: ?Sized + ser::Serialize,
38{
39    let vec = to_vec(value)?;
40    // JSON is always valid UTF8
41    unsafe { Ok(String::from_utf8_unchecked(vec)) }
42}
43
44/// Serializes a value as JSON into a writer.
45pub fn to_writer<W, T>(writer: W, value: &T) -> Result<(), Error>
46where
47    W: Write,
48    T: ?Sized + ser::Serialize,
49{
50    value.serialize(&mut Serializer::new(writer))
51}
52
53/// A serde JSON serializer compatible with the Conjure specification.
54pub struct Serializer<W, F = CompactFormatter>(serde_json::Serializer<W, F>);
55
56impl<W> Serializer<W>
57where
58    W: Write,
59{
60    /// Creates a new Conjure JSON serializer.
61    pub fn new(writer: W) -> Serializer<W> {
62        Serializer(serde_json::Serializer::new(writer))
63    }
64}
65
66impl<'a, W> Serializer<W, PrettyFormatter<'a>>
67where
68    W: Write,
69{
70    /// Creates a new Conjure pretty JSON serializer.
71    pub fn pretty(writer: W) -> Serializer<W, PrettyFormatter<'a>> {
72        Serializer(serde_json::Serializer::pretty(writer))
73    }
74}
75
76impl<W, F> Serializer<W, F>
77where
78    W: Write,
79    F: Formatter,
80{
81    /// Creates a new Conjure JSON serializer with a custom formatter.
82    pub fn with_formatter(writer: W, formatter: F) -> Serializer<W, F> {
83        Serializer(serde_json::Serializer::with_formatter(writer, formatter))
84    }
85
86    /// Returns the inner writer.
87    pub fn into_inner(self) -> W {
88        self.0.into_inner()
89    }
90}
91
92impl<'a, W, F> ser::Serializer for &'a mut Serializer<W, F>
93where
94    W: Write,
95    F: Formatter,
96{
97    impl_serialize_body!(&'a mut serde_json::Serializer<W, F>, ValueBehavior);
98
99    // we can't delegate this due to the signature, but luckily we know the answer
100    fn is_human_readable(&self) -> bool {
101        true
102    }
103}
104
105pub enum ValueBehavior {}
106
107impl Behavior for ValueBehavior {
108    type KeyBehavior = KeyBehavior;
109
110    fn serialize_f32<S>(ser: S, v: f32) -> Result<S::Ok, S::Error>
111    where
112        S: serde::Serializer,
113    {
114        if v.is_nan() {
115            ser.serialize_str("NaN")
116        } else if v == f32::INFINITY {
117            ser.serialize_str("Infinity")
118        } else if v == f32::NEG_INFINITY {
119            ser.serialize_str("-Infinity")
120        } else {
121            ser.serialize_f32(v)
122        }
123    }
124
125    fn serialize_f64<S>(ser: S, v: f64) -> Result<S::Ok, S::Error>
126    where
127        S: serde::Serializer,
128    {
129        if v.is_nan() {
130            ser.serialize_str("NaN")
131        } else if v == f64::INFINITY {
132            ser.serialize_str("Infinity")
133        } else if v == f64::NEG_INFINITY {
134            ser.serialize_str("-Infinity")
135        } else {
136            ser.serialize_f64(v)
137        }
138    }
139
140    fn serialize_bytes<S>(ser: S, v: &[u8]) -> Result<S::Ok, S::Error>
141    where
142        S: serde::Serializer,
143    {
144        ser.collect_str(&Base64Display::new(v, &STANDARD))
145    }
146}
147
148pub enum KeyBehavior {}
149
150impl Behavior for KeyBehavior {
151    type KeyBehavior = Self;
152
153    fn serialize_bool<S>(ser: S, v: bool) -> Result<S::Ok, S::Error>
154    where
155        S: serde::Serializer,
156    {
157        if v {
158            ser.serialize_str("true")
159        } else {
160            ser.serialize_str("false")
161        }
162    }
163
164    fn serialize_f32<S>(ser: S, v: f32) -> Result<S::Ok, S::Error>
165    where
166        S: serde::Serializer,
167    {
168        if v.is_nan() {
169            ser.serialize_str("NaN")
170        } else if v == f32::INFINITY {
171            ser.serialize_str("Infinity")
172        } else if v == f32::NEG_INFINITY {
173            ser.serialize_str("-Infinity")
174        } else {
175            ser.collect_str(&v)
176        }
177    }
178
179    fn serialize_f64<S>(ser: S, v: f64) -> Result<S::Ok, S::Error>
180    where
181        S: serde::Serializer,
182    {
183        if v.is_nan() {
184            ser.serialize_str("NaN")
185        } else if v == f64::INFINITY {
186            ser.serialize_str("Infinity")
187        } else if v == f64::NEG_INFINITY {
188            ser.serialize_str("-Infinity")
189        } else {
190            ser.collect_str(&v)
191        }
192    }
193
194    fn serialize_bytes<S>(ser: S, v: &[u8]) -> Result<S::Ok, S::Error>
195    where
196        S: serde::Serializer,
197    {
198        ser.collect_str(&Base64Display::new(v, &STANDARD))
199    }
200}