protobuf_json_mapping/
print.rs

1use std::fmt;
2use std::fmt::Write as fmt_Write;
3
4use protobuf::reflect::EnumDescriptor;
5use protobuf::reflect::EnumValueDescriptor;
6use protobuf::reflect::MessageRef;
7use protobuf::reflect::ReflectFieldRef;
8use protobuf::reflect::ReflectMapRef;
9use protobuf::reflect::ReflectRepeatedRef;
10use protobuf::reflect::ReflectValueRef;
11use protobuf::reflect::RuntimeFieldType;
12use protobuf::reflect::RuntimeType;
13use protobuf::well_known_types::any::Any;
14use protobuf::well_known_types::duration::Duration;
15use protobuf::well_known_types::field_mask::FieldMask;
16use protobuf::well_known_types::struct_::value;
17use protobuf::well_known_types::struct_::ListValue;
18use protobuf::well_known_types::struct_::NullValue;
19use protobuf::well_known_types::struct_::Struct;
20use protobuf::well_known_types::struct_::Value;
21use protobuf::well_known_types::timestamp::Timestamp;
22use protobuf::well_known_types::wrappers::BoolValue;
23use protobuf::well_known_types::wrappers::BytesValue;
24use protobuf::well_known_types::wrappers::DoubleValue;
25use protobuf::well_known_types::wrappers::FloatValue;
26use protobuf::well_known_types::wrappers::Int32Value;
27use protobuf::well_known_types::wrappers::Int64Value;
28use protobuf::well_known_types::wrappers::StringValue;
29use protobuf::well_known_types::wrappers::UInt32Value;
30use protobuf::well_known_types::wrappers::UInt64Value;
31use protobuf::MessageDyn;
32
33use crate::base64;
34use crate::float;
35use crate::rfc_3339::TmUtc;
36use crate::well_known_wrapper::WellKnownWrapper;
37
38#[derive(Debug, thiserror::Error)]
39enum PrintErrorInner {
40    #[error(transparent)]
41    Fmt(fmt::Error),
42    #[error("JSON printing of Any is not implemented")]
43    AnyPrintingIsNotImplemented,
44    #[error("Negative nanoseconds in timestamp")]
45    TimestampNegativeNanos,
46    #[error("Unknown struct value kind")]
47    UnknownStructValueKind,
48}
49
50/// Print to JSON error.
51#[derive(Debug, thiserror::Error)]
52#[error(transparent)]
53pub struct PrintError(PrintErrorInner);
54
55impl From<fmt::Error> for PrintError {
56    fn from(e: fmt::Error) -> Self {
57        PrintError(PrintErrorInner::Fmt(e))
58    }
59}
60
61pub type PrintResult<T> = Result<T, PrintError>;
62
63struct Printer {
64    buf: String,
65    print_options: PrintOptions,
66}
67
68trait PrintableToJson {
69    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()>;
70}
71
72trait JsonFloat: fmt::Display + fmt::Debug + PrintableToJson {
73    fn is_nan(&self) -> bool;
74    fn is_pos_infinity(&self) -> bool;
75    fn is_neg_infinity(&self) -> bool;
76
77    fn print_to_json_impl(&self, w: &mut String) -> PrintResult<()> {
78        Ok(if self.is_nan() {
79            write!(w, "\"{}\"", float::PROTOBUF_JSON_NAN)?
80        } else if self.is_pos_infinity() {
81            write!(w, "\"{}\"", float::PROTOBUF_JSON_INF)?
82        } else if self.is_neg_infinity() {
83            write!(w, "\"{}\"", float::PROTOBUF_JSON_MINUS_INF)?
84        } else {
85            write!(w, "{:?}", self)?
86        })
87    }
88}
89
90impl JsonFloat for f32 {
91    fn is_nan(&self) -> bool {
92        f32::is_nan(*self)
93    }
94
95    fn is_pos_infinity(&self) -> bool {
96        f32::is_infinite(*self) && self > &0.0
97    }
98
99    fn is_neg_infinity(&self) -> bool {
100        f32::is_infinite(*self) && self < &0.0
101    }
102}
103
104impl PrintableToJson for f32 {
105    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
106        Ok(self.print_to_json_impl(&mut w.buf)?)
107    }
108}
109
110impl JsonFloat for f64 {
111    fn is_nan(&self) -> bool {
112        f64::is_nan(*self)
113    }
114
115    fn is_pos_infinity(&self) -> bool {
116        f64::is_infinite(*self) && self > &0.0
117    }
118
119    fn is_neg_infinity(&self) -> bool {
120        f64::is_infinite(*self) && self < &0.0
121    }
122}
123
124impl PrintableToJson for f64 {
125    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
126        self.print_to_json_impl(&mut w.buf)
127    }
128}
129
130impl PrintableToJson for u64 {
131    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
132        // 64-bit integers are quoted by default
133        Ok(write!(w.buf, "\"{}\"", self)?)
134    }
135}
136
137impl PrintableToJson for i64 {
138    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
139        // 64-bit integers are quoted by default
140        Ok(write!(w.buf, "\"{}\"", self)?)
141    }
142}
143
144impl PrintableToJson for u32 {
145    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
146        Ok(write!(w.buf, "{}", self)?)
147    }
148}
149
150impl PrintableToJson for i32 {
151    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
152        Ok(write!(w.buf, "{}", self)?)
153    }
154}
155
156impl PrintableToJson for bool {
157    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
158        Ok(write!(w.buf, "{}", self)?)
159    }
160}
161
162impl PrintableToJson for str {
163    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
164        write!(w.buf, "\"")?;
165        for c in self.chars() {
166            match c {
167                '"' => write!(w.buf, "\\\""),
168                '\\' => write!(w.buf, "\\\\"),
169                '\n' => write!(w.buf, "\\n"),
170                '\r' => write!(w.buf, "\\r"),
171                '\t' => write!(w.buf, "\\t"),
172                c if c.is_control() => write!(w.buf, "\\u{:04x}", c as u32),
173                c => write!(w.buf, "{}", c),
174            }?;
175        }
176        write!(w.buf, "\"")?;
177        Ok(())
178    }
179}
180
181impl PrintableToJson for String {
182    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
183        self.as_str().print_to_json(w)
184    }
185}
186
187impl PrintableToJson for [u8] {
188    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
189        let encoded = base64::encode(self);
190        encoded.print_to_json(w)
191    }
192}
193
194impl PrintableToJson for Vec<u8> {
195    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
196        self.as_slice().print_to_json(w)
197    }
198}
199
200impl<'a> PrintableToJson for ReflectValueRef<'a> {
201    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
202        match self {
203            ReflectValueRef::U32(v) => w.print_printable(v),
204            ReflectValueRef::U64(v) => w.print_printable(v),
205            ReflectValueRef::I32(v) => w.print_printable(v),
206            ReflectValueRef::I64(v) => w.print_printable(v),
207            ReflectValueRef::F32(v) => w.print_printable(v),
208            ReflectValueRef::F64(v) => w.print_printable(v),
209            ReflectValueRef::Bool(v) => w.print_printable(v),
210            ReflectValueRef::String(v) => w.print_printable::<str>(v),
211            ReflectValueRef::Bytes(v) => w.print_printable::<[u8]>(v),
212            ReflectValueRef::Enum(d, v) => w.print_enum(d, *v),
213            ReflectValueRef::Message(v) => w.print_message(v),
214        }
215    }
216}
217
218impl PrintableToJson for Duration {
219    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
220        let sign = if self.seconds >= 0 { "" } else { "-" };
221        Ok(write!(
222            w.buf,
223            "\"{}{}.{:09}s\"",
224            sign,
225            self.seconds.abs(),
226            self.nanos.abs()
227        )?)
228    }
229}
230
231impl PrintableToJson for Timestamp {
232    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
233        if self.nanos < 0 {
234            return Err(PrintError(PrintErrorInner::TimestampNegativeNanos));
235        }
236        let tm_utc = TmUtc::from_protobuf_timestamp(self.seconds, self.nanos as u32);
237        w.print_printable(&tm_utc.to_string())
238    }
239}
240
241impl PrintableToJson for FieldMask {
242    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
243        w.print_printable(&self.paths.join(","))
244    }
245}
246
247impl PrintableToJson for Any {
248    fn print_to_json(&self, _w: &mut Printer) -> PrintResult<()> {
249        Err(PrintError(PrintErrorInner::AnyPrintingIsNotImplemented))
250    }
251}
252
253impl PrintableToJson for Value {
254    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
255        match self.kind {
256            // None should not be possible here, but it's better to print null than crash
257            None => w.print_json_null(),
258            Some(value::Kind::NullValue(null_value)) => {
259                match null_value.enum_value() {
260                    Ok(value) => w.print_wk_null_value(&value),
261                    Err(n) => {
262                        // Practically not possible, but it is safer this way.
263                        w.print_printable(&n)
264                    }
265                }
266            }
267            Some(value::Kind::BoolValue(b)) => w.print_printable(&b),
268            Some(value::Kind::NumberValue(n)) => w.print_printable(&n),
269            Some(value::Kind::StringValue(ref s)) => w.print_printable::<String>(&s),
270            Some(value::Kind::StructValue(ref s)) => w.print_printable(&s),
271            Some(value::Kind::ListValue(ref l)) => w.print_printable(&l),
272            Some(_) => Err(PrintError(PrintErrorInner::UnknownStructValueKind)),
273        }
274    }
275}
276
277impl PrintableToJson for ListValue {
278    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
279        w.print_list(&self.values)
280    }
281}
282
283impl PrintableToJson for Struct {
284    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
285        w.print_object(&self.fields)
286    }
287}
288
289impl<'a, P: PrintableToJson> PrintableToJson for &'a P {
290    fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
291        (*self).print_to_json(w)
292    }
293}
294
295trait ObjectKey {
296    fn print_object_key(&self, w: &mut Printer) -> PrintResult<()>;
297}
298
299impl<'a> ObjectKey for ReflectValueRef<'a> {
300    fn print_object_key(&self, w: &mut Printer) -> PrintResult<()> {
301        match self {
302            ReflectValueRef::String(v) => return w.print_printable::<str>(v),
303            ReflectValueRef::Bytes(v) => return w.print_printable::<[u8]>(v),
304            // do not quote, because printable is quoted
305            ReflectValueRef::U64(v) => return w.print_printable(v),
306            ReflectValueRef::I64(v) => return w.print_printable(v),
307            ReflectValueRef::Enum(d, v) if !w.print_options.enum_values_int => {
308                return w.print_enum(d, *v)
309            }
310            _ => {}
311        }
312
313        write!(w.buf, "\"")?;
314
315        match self {
316            ReflectValueRef::U32(v) => w.print_printable(v),
317            ReflectValueRef::I32(v) => w.print_printable(v),
318            ReflectValueRef::Bool(v) => w.print_printable(v),
319            ReflectValueRef::Enum(d, v) if w.print_options.enum_values_int => w.print_enum(d, *v),
320            ReflectValueRef::Enum(..)
321            | ReflectValueRef::U64(_)
322            | ReflectValueRef::I64(_)
323            | ReflectValueRef::String(_)
324            | ReflectValueRef::Bytes(_) => unreachable!(),
325            ReflectValueRef::F32(_) | ReflectValueRef::F64(_) | ReflectValueRef::Message(_) => {
326                panic!("cannot be object key")
327            }
328        }?;
329
330        write!(w.buf, "\"")?;
331
332        Ok(())
333    }
334}
335
336impl ObjectKey for String {
337    fn print_object_key(&self, w: &mut Printer) -> PrintResult<()> {
338        w.print_printable(self)
339    }
340}
341
342impl<'a, O: ObjectKey> ObjectKey for &'a O {
343    fn print_object_key(&self, w: &mut Printer) -> PrintResult<()> {
344        (*self).print_object_key(w)
345    }
346}
347
348impl Printer {
349    fn print_comma_but_first(&mut self, first: &mut bool) -> fmt::Result {
350        if *first {
351            *first = false;
352            Ok(())
353        } else {
354            write!(self.buf, ", ")
355        }
356    }
357
358    fn print_json_null(&mut self) -> PrintResult<()> {
359        Ok(write!(self.buf, "null")?)
360    }
361
362    fn print_printable<F: PrintableToJson + ?Sized>(&mut self, f: &F) -> PrintResult<()> {
363        f.print_to_json(self)
364    }
365
366    fn print_list<I>(&mut self, items: I) -> PrintResult<()>
367    where
368        I: IntoIterator,
369        I::Item: PrintableToJson,
370    {
371        write!(self.buf, "[")?;
372        for (i, item) in items.into_iter().enumerate() {
373            if i != 0 {
374                write!(self.buf, ", ")?;
375            }
376            self.print_printable(&item)?;
377        }
378        write!(self.buf, "]")?;
379        Ok(())
380    }
381
382    fn print_repeated(&mut self, repeated: &ReflectRepeatedRef) -> PrintResult<()> {
383        self.print_list(repeated)
384    }
385
386    fn print_object<I, K, V>(&mut self, items: I) -> PrintResult<()>
387    where
388        I: IntoIterator<Item = (K, V)>,
389        K: ObjectKey,
390        V: PrintableToJson,
391    {
392        write!(self.buf, "{{")?;
393        for (i, (k, v)) in items.into_iter().enumerate() {
394            if i != 0 {
395                write!(self.buf, ", ")?;
396            }
397            k.print_object_key(self)?;
398            write!(self.buf, ": ")?;
399            self.print_printable(&v)?;
400        }
401        write!(self.buf, "}}")?;
402        Ok(())
403    }
404
405    fn print_map(&mut self, map: &ReflectMapRef) -> PrintResult<()> {
406        self.print_object(map.into_iter())
407    }
408
409    fn print_enum_known(&mut self, value: &EnumValueDescriptor) -> PrintResult<()> {
410        if let Some(null_value) = value.cast() {
411            self.print_wk_null_value(&null_value)
412        } else {
413            if self.print_options.enum_values_int {
414                self.print_printable(&value.value())
415            } else {
416                Ok(write!(self.buf, "\"{}\"", value.name())?)
417            }
418        }
419    }
420
421    fn print_enum(&mut self, descriptor: &EnumDescriptor, v: i32) -> PrintResult<()> {
422        if self.print_options.enum_values_int {
423            self.print_printable(&v)
424        } else {
425            match descriptor.value_by_number(v) {
426                Some(value) => self.print_enum_known(&value),
427                None => self.print_printable(&v),
428            }
429        }
430    }
431
432    fn print_message(&mut self, message: &MessageRef) -> PrintResult<()> {
433        if let Some(duration) = message.downcast_ref::<Duration>() {
434            self.print_printable(duration)
435        } else if let Some(timestamp) = message.downcast_ref::<Timestamp>() {
436            self.print_printable(timestamp)
437        } else if let Some(field_mask) = message.downcast_ref::<FieldMask>() {
438            self.print_printable(field_mask)
439        } else if let Some(any) = message.downcast_ref::<Any>() {
440            self.print_printable(any)
441        } else if let Some(value) = message.downcast_ref::<Value>() {
442            self.print_printable(value)
443        } else if let Some(value) = message.downcast_ref::<DoubleValue>() {
444            self.print_wrapper(value)
445        } else if let Some(value) = message.downcast_ref::<FloatValue>() {
446            self.print_wrapper(value)
447        } else if let Some(value) = message.downcast_ref::<Int64Value>() {
448            self.print_wrapper(value)
449        } else if let Some(value) = message.downcast_ref::<UInt64Value>() {
450            self.print_wrapper(value)
451        } else if let Some(value) = message.downcast_ref::<Int32Value>() {
452            self.print_wrapper(value)
453        } else if let Some(value) = message.downcast_ref::<UInt32Value>() {
454            self.print_wrapper(value)
455        } else if let Some(value) = message.downcast_ref::<BoolValue>() {
456            self.print_wrapper(value)
457        } else if let Some(value) = message.downcast_ref::<StringValue>() {
458            self.print_wrapper(value)
459        } else if let Some(value) = message.downcast_ref::<BytesValue>() {
460            self.print_wrapper(value)
461        } else if let Some(value) = message.downcast_ref::<ListValue>() {
462            self.print_printable(value)
463        } else if let Some(value) = message.downcast_ref::<Struct>() {
464            self.print_printable(value)
465        } else {
466            self.print_regular_message(message)
467        }
468    }
469
470    fn print_regular_message(&mut self, message: &MessageRef) -> Result<(), PrintError> {
471        let descriptor = message.descriptor_dyn();
472
473        write!(self.buf, "{{")?;
474        let mut first = true;
475        for field in descriptor.fields() {
476            let json_field_name = if self.print_options.proto_field_name {
477                field.name()
478            } else {
479                field.json_name()
480            };
481
482            let field_type = field.runtime_field_type();
483
484            match field.get_reflect(&**message) {
485                ReflectFieldRef::Optional(v) => match v.value() {
486                    None => {
487                        if self.print_options.always_output_default_values {
488                            let is_message = match field_type {
489                                RuntimeFieldType::Singular(s) => match s {
490                                    RuntimeType::Message(_) => true,
491                                    _ => false,
492                                },
493                                _ => unreachable!(),
494                            };
495
496                            let is_oneof = field.proto().has_oneof_index();
497
498                            if !is_message && !is_oneof {
499                                let v = field.get_singular_field_or_default(&**message);
500                                self.print_comma_but_first(&mut first)?;
501                                write!(self.buf, "\"{}\": ", json_field_name)?;
502                                self.print_printable(&v)?;
503                            }
504                        }
505                    }
506                    Some(v) => {
507                        self.print_comma_but_first(&mut first)?;
508                        write!(self.buf, "\"{}\": ", json_field_name)?;
509                        self.print_printable(&v)?;
510                    }
511                },
512                ReflectFieldRef::Repeated(v) => {
513                    if !v.is_empty() || self.print_options.always_output_default_values {
514                        self.print_comma_but_first(&mut first)?;
515                        write!(self.buf, "\"{}\": ", json_field_name)?;
516                        self.print_repeated(&v)?;
517                    }
518                }
519                ReflectFieldRef::Map(v) => {
520                    if !v.is_empty() || self.print_options.always_output_default_values {
521                        self.print_comma_but_first(&mut first)?;
522                        write!(self.buf, "\"{}\": ", json_field_name)?;
523                        self.print_map(&v)?;
524                    }
525                }
526            }
527        }
528        write!(self.buf, "}}")?;
529        Ok(())
530    }
531
532    fn print_wk_null_value(&mut self, _null_value: &NullValue) -> PrintResult<()> {
533        self.print_json_null()
534    }
535
536    fn print_wrapper<W>(&mut self, value: &W) -> PrintResult<()>
537    where
538        W: WellKnownWrapper,
539        W::Underlying: PrintableToJson,
540    {
541        self.print_printable(value.get_ref())
542    }
543}
544
545/// Options for printing JSON to string
546///
547/// # Examples
548///
549/// ```
550/// let print_options = protobuf_json_mapping::PrintOptions {
551///     enum_values_int: true,
552///     ..Default::default()
553/// };
554/// ```
555#[derive(Default, Debug, Clone)]
556pub struct PrintOptions {
557    /// Use ints instead of strings for enums.
558    ///
559    /// Note both string or int can be parsed.
560    pub enum_values_int: bool,
561    /// Use protobuf field names instead of `lowerCamelCase` which is used by default.
562    /// Note both names are supported when JSON is parsed.
563    pub proto_field_name: bool,
564    /// Output field default values.
565    pub always_output_default_values: bool,
566    /// Prevent initializing `PrintOptions` enumerating all field.
567    pub _future_options: (),
568}
569
570/// Serialize message to JSON according to protobuf specification.
571pub fn print_to_string_with_options(
572    message: &dyn MessageDyn,
573    print_options: &PrintOptions,
574) -> PrintResult<String> {
575    let mut printer = Printer {
576        buf: String::new(),
577        print_options: print_options.clone(),
578    };
579    printer.print_message(&MessageRef::from(message))?;
580    Ok(printer.buf)
581}
582
583/// Serialize message to JSON according to protobuf specification.
584pub fn print_to_string(message: &dyn MessageDyn) -> PrintResult<String> {
585    print_to_string_with_options(message, &PrintOptions::default())
586}