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