1 use std::fmt;
2 use std::fmt::Write as fmt_Write;
3 
4 use protobuf::reflect::EnumDescriptor;
5 use protobuf::reflect::EnumValueDescriptor;
6 use protobuf::reflect::MessageRef;
7 use protobuf::reflect::ReflectFieldRef;
8 use protobuf::reflect::ReflectMapRef;
9 use protobuf::reflect::ReflectRepeatedRef;
10 use protobuf::reflect::ReflectValueRef;
11 use protobuf::reflect::RuntimeFieldType;
12 use protobuf::reflect::RuntimeType;
13 use protobuf::well_known_types::any::Any;
14 use protobuf::well_known_types::duration::Duration;
15 use protobuf::well_known_types::field_mask::FieldMask;
16 use protobuf::well_known_types::struct_::value;
17 use protobuf::well_known_types::struct_::ListValue;
18 use protobuf::well_known_types::struct_::NullValue;
19 use protobuf::well_known_types::struct_::Struct;
20 use protobuf::well_known_types::struct_::Value;
21 use protobuf::well_known_types::timestamp::Timestamp;
22 use protobuf::well_known_types::wrappers::BoolValue;
23 use protobuf::well_known_types::wrappers::BytesValue;
24 use protobuf::well_known_types::wrappers::DoubleValue;
25 use protobuf::well_known_types::wrappers::FloatValue;
26 use protobuf::well_known_types::wrappers::Int32Value;
27 use protobuf::well_known_types::wrappers::Int64Value;
28 use protobuf::well_known_types::wrappers::StringValue;
29 use protobuf::well_known_types::wrappers::UInt32Value;
30 use protobuf::well_known_types::wrappers::UInt64Value;
31 use protobuf::MessageDyn;
32 
33 use crate::base64;
34 use crate::float;
35 use crate::rfc_3339::TmUtc;
36 use crate::well_known_wrapper::WellKnownWrapper;
37 
38 #[derive(Debug, thiserror::Error)]
39 enum 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)]
53 pub struct PrintError(PrintErrorInner);
54 
55 impl From<fmt::Error> for PrintError {
from(e: fmt::Error) -> Self56     fn from(e: fmt::Error) -> Self {
57         PrintError(PrintErrorInner::Fmt(e))
58     }
59 }
60 
61 pub type PrintResult<T> = Result<T, PrintError>;
62 
63 struct Printer {
64     buf: String,
65     print_options: PrintOptions,
66 }
67 
68 trait PrintableToJson {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>69     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()>;
70 }
71 
72 trait JsonFloat: fmt::Display + fmt::Debug + PrintableToJson {
is_nan(&self) -> bool73     fn is_nan(&self) -> bool;
is_pos_infinity(&self) -> bool74     fn is_pos_infinity(&self) -> bool;
is_neg_infinity(&self) -> bool75     fn is_neg_infinity(&self) -> bool;
76 
print_to_json_impl(&self, w: &mut String) -> PrintResult<()>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 
90 impl JsonFloat for f32 {
is_nan(&self) -> bool91     fn is_nan(&self) -> bool {
92         f32::is_nan(*self)
93     }
94 
is_pos_infinity(&self) -> bool95     fn is_pos_infinity(&self) -> bool {
96         f32::is_infinite(*self) && self > &0.0
97     }
98 
is_neg_infinity(&self) -> bool99     fn is_neg_infinity(&self) -> bool {
100         f32::is_infinite(*self) && self < &0.0
101     }
102 }
103 
104 impl PrintableToJson for f32 {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>105     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
106         Ok(self.print_to_json_impl(&mut w.buf)?)
107     }
108 }
109 
110 impl JsonFloat for f64 {
is_nan(&self) -> bool111     fn is_nan(&self) -> bool {
112         f64::is_nan(*self)
113     }
114 
is_pos_infinity(&self) -> bool115     fn is_pos_infinity(&self) -> bool {
116         f64::is_infinite(*self) && self > &0.0
117     }
118 
is_neg_infinity(&self) -> bool119     fn is_neg_infinity(&self) -> bool {
120         f64::is_infinite(*self) && self < &0.0
121     }
122 }
123 
124 impl PrintableToJson for f64 {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>125     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
126         self.print_to_json_impl(&mut w.buf)
127     }
128 }
129 
130 impl PrintableToJson for u64 {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
137 impl PrintableToJson for i64 {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
144 impl PrintableToJson for u32 {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>145     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
146         Ok(write!(w.buf, "{}", self)?)
147     }
148 }
149 
150 impl PrintableToJson for i32 {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>151     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
152         Ok(write!(w.buf, "{}", self)?)
153     }
154 }
155 
156 impl PrintableToJson for bool {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>157     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
158         Ok(write!(w.buf, "{}", self)?)
159     }
160 }
161 
162 impl PrintableToJson for str {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
181 impl PrintableToJson for String {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>182     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
183         self.as_str().print_to_json(w)
184     }
185 }
186 
187 impl PrintableToJson for [u8] {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
194 impl PrintableToJson for Vec<u8> {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>195     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
196         self.as_slice().print_to_json(w)
197     }
198 }
199 
200 impl<'a> PrintableToJson for ReflectValueRef<'a> {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
218 impl PrintableToJson for Duration {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
231 impl PrintableToJson for Timestamp {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
241 impl PrintableToJson for FieldMask {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>242     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
243         w.print_printable(&self.paths.join(","))
244     }
245 }
246 
247 impl PrintableToJson for Any {
print_to_json(&self, _w: &mut Printer) -> PrintResult<()>248     fn print_to_json(&self, _w: &mut Printer) -> PrintResult<()> {
249         Err(PrintError(PrintErrorInner::AnyPrintingIsNotImplemented))
250     }
251 }
252 
253 impl PrintableToJson for Value {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>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 
277 impl PrintableToJson for ListValue {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>278     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
279         w.print_list(&self.values)
280     }
281 }
282 
283 impl PrintableToJson for Struct {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>284     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
285         w.print_object(&self.fields)
286     }
287 }
288 
289 impl<'a, P: PrintableToJson> PrintableToJson for &'a P {
print_to_json(&self, w: &mut Printer) -> PrintResult<()>290     fn print_to_json(&self, w: &mut Printer) -> PrintResult<()> {
291         (*self).print_to_json(w)
292     }
293 }
294 
295 trait ObjectKey {
print_object_key(&self, w: &mut Printer) -> PrintResult<()>296     fn print_object_key(&self, w: &mut Printer) -> PrintResult<()>;
297 }
298 
299 impl<'a> ObjectKey for ReflectValueRef<'a> {
print_object_key(&self, w: &mut Printer) -> PrintResult<()>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 
336 impl ObjectKey for String {
print_object_key(&self, w: &mut Printer) -> PrintResult<()>337     fn print_object_key(&self, w: &mut Printer) -> PrintResult<()> {
338         w.print_printable(self)
339     }
340 }
341 
342 impl<'a, O: ObjectKey> ObjectKey for &'a O {
print_object_key(&self, w: &mut Printer) -> PrintResult<()>343     fn print_object_key(&self, w: &mut Printer) -> PrintResult<()> {
344         (*self).print_object_key(w)
345     }
346 }
347 
348 impl Printer {
print_comma_but_first(&mut self, first: &mut bool) -> fmt::Result349     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 
print_json_null(&mut self) -> PrintResult<()>358     fn print_json_null(&mut self) -> PrintResult<()> {
359         Ok(write!(self.buf, "null")?)
360     }
361 
print_printable<F: PrintableToJson + ?Sized>(&mut self, f: &F) -> PrintResult<()>362     fn print_printable<F: PrintableToJson + ?Sized>(&mut self, f: &F) -> PrintResult<()> {
363         f.print_to_json(self)
364     }
365 
print_list<I>(&mut self, items: I) -> PrintResult<()> where I: IntoIterator, I::Item: PrintableToJson,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 
print_repeated(&mut self, repeated: &ReflectRepeatedRef) -> PrintResult<()>382     fn print_repeated(&mut self, repeated: &ReflectRepeatedRef) -> PrintResult<()> {
383         self.print_list(repeated)
384     }
385 
print_object<I, K, V>(&mut self, items: I) -> PrintResult<()> where I: IntoIterator<Item = (K, V)>, K: ObjectKey, V: PrintableToJson,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 
print_map(&mut self, map: &ReflectMapRef) -> PrintResult<()>405     fn print_map(&mut self, map: &ReflectMapRef) -> PrintResult<()> {
406         self.print_object(map.into_iter())
407     }
408 
print_enum_known(&mut self, value: &EnumValueDescriptor) -> PrintResult<()>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 
print_enum(&mut self, descriptor: &EnumDescriptor, v: i32) -> PrintResult<()>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 
print_message(&mut self, message: &MessageRef) -> PrintResult<()>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 
print_regular_message(&mut self, message: &MessageRef) -> Result<(), PrintError>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 
print_wk_null_value(&mut self, _null_value: &NullValue) -> PrintResult<()>532     fn print_wk_null_value(&mut self, _null_value: &NullValue) -> PrintResult<()> {
533         self.print_json_null()
534     }
535 
print_wrapper<W>(&mut self, value: &W) -> PrintResult<()> where W: WellKnownWrapper, W::Underlying: PrintableToJson,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)]
556 pub 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.
print_to_string_with_options( message: &dyn MessageDyn, print_options: &PrintOptions, ) -> PrintResult<String>571 pub 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.
print_to_string(message: &dyn MessageDyn) -> PrintResult<String>584 pub fn print_to_string(message: &dyn MessageDyn) -> PrintResult<String> {
585     print_to_string_with_options(message, &PrintOptions::default())
586 }
587