1use std::fmt::{self, Write};
2
3use prost::Message;
4
5use crate::{
6 dynamic::{
7 fields::ValueAndDescriptor,
8 fmt_string, get_type_url_message_name,
9 text_format::FormatOptions,
10 unknown::{UnknownField, UnknownFieldSet, UnknownFieldValue},
11 },
12 DynamicMessage, Kind, MapKey, Value,
13};
14
15pub(in crate::dynamic) struct Writer<'a, W> {
16 options: FormatOptions,
17 f: &'a mut W,
18 indent_level: u32,
19}
20
21impl<'a, W> Writer<'a, W>
22where
23 W: Write,
24{
25 pub fn new(options: FormatOptions, f: &'a mut W) -> Self {
26 Writer {
27 options,
28 f,
29 indent_level: 0,
30 }
31 }
32
33 pub fn fmt_message(&mut self, message: &DynamicMessage) -> fmt::Result {
34 if self.options.expand_any {
35 if let Some((type_url, body)) = as_any(message) {
36 self.f.write_char('[')?;
37 self.f.write_str(&type_url)?;
38 self.f.write_str("]")?;
39 self.fmt_field_value(&Value::Message(body), None)?;
40 return Ok(());
41 }
42 }
43
44 let fields = message.fields.iter(
45 &message.desc,
46 !self.options.skip_default_fields,
47 self.options.print_message_fields_in_index_order,
48 );
49
50 if self.options.skip_unknown_fields {
51 self.fmt_delimited(
52 fields.filter(|f| !matches!(f, ValueAndDescriptor::Unknown(..))),
53 Writer::fmt_message_field,
54 )
55 } else {
56 self.fmt_delimited(fields, Writer::fmt_message_field)
57 }
58 }
59
60 pub fn fmt_value(&mut self, value: &Value, kind: Option<&Kind>) -> fmt::Result {
61 match value {
62 Value::Bool(value) => write!(self.f, "{}", value),
63 Value::I32(value) => write!(self.f, "{}", value),
64 Value::I64(value) => write!(self.f, "{}", value),
65 Value::U32(value) => write!(self.f, "{}", value),
66 Value::U64(value) => write!(self.f, "{}", value),
67 Value::F32(value) => {
68 if value.fract() == 0.0 {
69 write!(self.f, "{:.1}", value)
70 } else {
71 write!(self.f, "{}", value)
72 }
73 }
74 Value::F64(value) => {
75 if value.fract() == 0.0 {
76 write!(self.f, "{:.1}", value)
77 } else {
78 write!(self.f, "{}", value)
79 }
80 }
81 Value::String(s) => self.fmt_string(s.as_bytes()),
82 Value::Bytes(s) => self.fmt_string(s.as_ref()),
83 Value::EnumNumber(value) => {
84 if let Some(Kind::Enum(desc)) = kind {
85 if let Some(value) = desc.get_value(*value) {
86 return self.f.write_str(value.name());
87 }
88 }
89 write!(self.f, "{}", value)
90 }
91 Value::Message(message) => {
92 let mut fields = message.fields.iter(
93 &message.desc,
94 !self.options.skip_default_fields,
95 self.options.print_message_fields_in_index_order,
96 );
97
98 if fields.all(|f| {
99 self.options.skip_unknown_fields && matches!(f, ValueAndDescriptor::Unknown(..))
100 }) {
101 self.f.write_str("{}")
102 } else if self.options.pretty {
103 self.f.write_char('{')?;
104 self.indent_level += 2;
105 self.fmt_newline()?;
106 self.fmt_message(message)?;
107 self.indent_level -= 2;
108 self.fmt_newline()?;
109 self.f.write_char('}')
110 } else {
111 self.f.write_char('{')?;
112 self.fmt_message(message)?;
113 self.f.write_char('}')
114 }
115 }
116 Value::List(list) => {
117 self.fmt_list(list.iter(), |this, value| this.fmt_value(value, kind))
118 }
119 Value::Map(map) => {
120 let value_kind = kind
121 .and_then(|k| k.as_message())
122 .map(|m| m.map_entry_value_field().kind());
123 self.fmt_list(map.iter(), |this, (key, value)| {
124 if this.options.pretty {
125 this.f.write_str("{")?;
126 this.indent_level += 2;
127 this.fmt_newline()?;
128 this.f.write_str("key: ")?;
129 this.fmt_map_key(key)?;
130 this.fmt_newline()?;
131 this.f.write_str("value")?;
132 this.fmt_field_value(value, value_kind.as_ref())?;
133 this.indent_level -= 2;
134 this.fmt_newline()?;
135 this.f.write_char('}')
136 } else {
137 this.f.write_str("{key:")?;
138 this.fmt_map_key(key)?;
139 this.f.write_str(",value")?;
140 this.fmt_field_value(value, value_kind.as_ref())?;
141 this.f.write_char('}')
142 }
143 })
144 }
145 }
146 }
147
148 fn fmt_map_key(&mut self, value: &MapKey) -> fmt::Result {
149 match value {
150 MapKey::Bool(value) => write!(self.f, "{}", value),
151 MapKey::I32(value) => write!(self.f, "{}", value),
152 MapKey::I64(value) => write!(self.f, "{}", value),
153 MapKey::U32(value) => write!(self.f, "{}", value),
154 MapKey::U64(value) => write!(self.f, "{}", value),
155 MapKey::String(s) => self.fmt_string(s.as_bytes()),
156 }
157 }
158
159 fn fmt_message_field(&mut self, field: ValueAndDescriptor) -> fmt::Result {
160 match field {
161 ValueAndDescriptor::Field(value, desc) => {
162 if desc.is_group() {
163 write!(self.f, "{}", desc.kind().as_message().unwrap().name())?;
164 } else {
165 write!(self.f, "{}", desc.name())?;
166 }
167 self.fmt_field_value(&value, Some(&desc.kind()))
168 }
169 ValueAndDescriptor::Extension(value, desc) => {
170 write!(self.f, "[{}]", desc.full_name())?;
171 self.fmt_field_value(&value, Some(&desc.kind()))
172 }
173 ValueAndDescriptor::Unknown(values) => {
174 self.fmt_delimited(values.iter(), Writer::fmt_unknown_field)
175 }
176 }
177 }
178
179 fn fmt_field_value(&mut self, value: &Value, kind: Option<&Kind>) -> fmt::Result {
180 if !matches!(value, Value::Message(_)) {
181 self.f.write_char(':')?;
182 }
183 self.fmt_padding()?;
184 self.fmt_value(value, kind)
185 }
186
187 pub fn fmt_unknown_field(&mut self, field: &UnknownField) -> fmt::Result {
188 write!(self.f, "{}", field.number())?;
189 match field.value() {
190 UnknownFieldValue::Varint(int) => {
191 self.f.write_char(':')?;
192 self.fmt_padding()?;
193 write!(self.f, "{}", int)
194 }
195 UnknownFieldValue::ThirtyTwoBit(bytes) => {
196 self.f.write_char(':')?;
197 self.fmt_padding()?;
198 write!(self.f, "0x{:08x}", u32::from_le_bytes(*bytes))
199 }
200 UnknownFieldValue::SixtyFourBit(bytes) => {
201 self.f.write_char(':')?;
202 self.fmt_padding()?;
203 write!(self.f, "0x{:016x}", u64::from_le_bytes(*bytes))
204 }
205 UnknownFieldValue::LengthDelimited(bytes) => {
206 if !bytes.is_empty() {
207 if let Ok(set) = UnknownFieldSet::decode(bytes.clone()) {
208 self.fmt_padding()?;
209 return self.fmt_unknown_field_set(&set);
210 }
211 }
212
213 self.f.write_char(':')?;
214 self.fmt_padding()?;
215 self.fmt_string(bytes.as_ref())
216 }
217 UnknownFieldValue::Group(set) => {
218 self.fmt_padding()?;
219 self.fmt_unknown_field_set(set)
220 }
221 }
222 }
223
224 fn fmt_unknown_field_set(&mut self, set: &UnknownFieldSet) -> fmt::Result {
225 if set.is_empty() {
226 self.f.write_str("{}")
227 } else if self.options.pretty {
228 self.f.write_char('{')?;
229 self.indent_level += 2;
230 self.fmt_newline()?;
231 self.fmt_delimited(set.iter(), Writer::fmt_unknown_field)?;
232 self.indent_level -= 2;
233 self.fmt_newline()?;
234 self.f.write_char('}')
235 } else {
236 self.f.write_char('{')?;
237 self.fmt_delimited(set.iter(), Writer::fmt_unknown_field)?;
238 self.f.write_char('}')
239 }
240 }
241
242 fn fmt_string(&mut self, bytes: &[u8]) -> fmt::Result {
243 fmt_string(&mut self.f, bytes)
244 }
245
246 fn fmt_delimited<T>(
247 &mut self,
248 mut iter: impl Iterator<Item = T>,
249 f: impl Fn(&mut Self, T) -> fmt::Result,
250 ) -> fmt::Result {
251 if let Some(first) = iter.next() {
252 f(self, first)?;
253 }
254 for item in iter {
255 if self.options.pretty {
256 self.fmt_newline()?;
257 } else {
258 self.f.write_char(',')?;
259 }
260 f(self, item)?;
261 }
262
263 Ok(())
264 }
265
266 fn fmt_list<I>(
267 &mut self,
268 mut iter: impl Iterator<Item = I>,
269 f: impl Fn(&mut Self, I) -> fmt::Result,
270 ) -> fmt::Result {
271 self.f.write_char('[')?;
272 if let Some(first) = iter.next() {
273 f(self, first)?;
274 }
275 for item in iter {
276 self.f.write_char(',')?;
277 self.fmt_padding()?;
278 f(self, item)?;
279 }
280 self.f.write_char(']')
281 }
282
283 fn fmt_padding(&mut self) -> fmt::Result {
284 if self.options.pretty {
285 self.f.write_char(' ')?;
286 }
287 Ok(())
288 }
289
290 fn fmt_newline(&mut self) -> fmt::Result {
291 self.f.write_char('\n')?;
292 for _ in 0..self.indent_level {
293 self.f.write_char(' ')?;
294 }
295 Ok(())
296 }
297}
298
299fn as_any(message: &DynamicMessage) -> Option<(String, DynamicMessage)> {
300 if message.desc.full_name() != "google.protobuf.Any" {
301 return None;
302 }
303
304 let any = message.transcode_to::<prost_types::Any>().ok()?;
305 let message_name = get_type_url_message_name(&any.type_url).ok()?;
306
307 let desc = message
308 .desc
309 .parent_pool()
310 .get_message_by_name(message_name)?;
311 let body = DynamicMessage::decode(desc, any.value.as_slice()).ok()?;
312 Some((any.type_url, body))
313}
314
315#[cfg(test)]
316#[cfg(feature = "text-format")]
317mod tests {
318 use super::*;
319 use crate::ReflectMessage;
320
321 fn fmt_unknown(value: &UnknownFieldSet) -> String {
322 let mut string = String::new();
323 Writer::new(FormatOptions::new().skip_unknown_fields(false), &mut string)
324 .fmt_delimited(value.iter(), Writer::fmt_unknown_field)
325 .unwrap();
326 string
327 }
328
329 fn fmt_unknown_pretty(value: &UnknownFieldSet) -> String {
330 let mut string = String::new();
331 Writer::new(
332 FormatOptions::new().skip_unknown_fields(false).pretty(true),
333 &mut string,
334 )
335 .fmt_delimited(value.iter(), Writer::fmt_unknown_field)
336 .unwrap();
337 string
338 }
339
340 #[test]
341 fn fmt_unknown_scalar() {
342 let value = UnknownFieldSet::decode(b"\x09\x9a\x99\x99\x99\x99\x99\xf1\x3f\x15\xcd\xcc\x0c\x40\x18\x03\x20\x04\x28\x05\x30\x06\x38\x0e\x40\x10\x4d\x09\x00\x00\x00\x51\x0a\x00\x00\x00\x00\x00\x00\x00\x5d\x0b\x00\x00\x00\x61\x0c\x00\x00\x00\x00\x00\x00\x00\x68\x01\x72\x01\x35\x7a\x07\x69\xa6\xbe\x6d\xb6\xff\x58".as_ref()).unwrap();
343 assert_eq!(
344 fmt_unknown(&value),
345 r#"1:0x3ff199999999999a,2:0x400ccccd,3:3,4:4,5:5,6:6,7:14,8:16,9:0x00000009,10:0x000000000000000a,11:0x0000000b,12:0x000000000000000c,13:1,14:"5",15:"i\246\276m\266\377X""#
346 );
347 assert_eq!(
348 fmt_unknown_pretty(&value),
349 r#"1: 0x3ff199999999999a
3502: 0x400ccccd
3513: 3
3524: 4
3535: 5
3546: 6
3557: 14
3568: 16
3579: 0x00000009
35810: 0x000000000000000a
35911: 0x0000000b
36012: 0x000000000000000c
36113: 1
36214: "5"
36315: "i\246\276m\266\377X""#
364 );
365 }
366
367 #[test]
368 fn fmt_unknown_complex_type() {
369 let value = UnknownFieldSet::decode(b"\x0a\x15\x0a\x01\x31\x12\x10\x09\x9a\x99\x99\x99\x99\x99\xf1\x3f\x15\xcd\xcc\x0c\x40\x18\x03\x12\x0d\x08\x03\x12\x09\x38\x0e\x40\x10\x4d\x09\x00\x00\x00\x1a\x16\x5d\x0b\x00\x00\x00\x61\x0c\x00\x00\x00\x00\x00\x00\x00\x68\x01\x72\x01\x35\x7a\x01\x36\x22\x0e\x00\x01\x02\x03\xfc\xff\xff\xff\xff\xff\xff\xff\xff\x01\x28\x01".as_ref()).unwrap();
370 assert_eq!(
371 fmt_unknown(&value),
372 r#"1{1:"1",2{1:0x3ff199999999999a,2:0x400ccccd,3:3}},2{1:3,2{7:14,8:16,9:0x00000009}},3{11:0x0000000b,12:0x000000000000000c,13:1,14:"5",15:"6"},4:"\000\001\002\003\374\377\377\377\377\377\377\377\377\001",5:1"#
373 );
374 assert_eq!(
375 fmt_unknown_pretty(&value),
376 r#"1 {
377 1: "1"
378 2 {
379 1: 0x3ff199999999999a
380 2: 0x400ccccd
381 3: 3
382 }
383}
3842 {
385 1: 3
386 2 {
387 7: 14
388 8: 16
389 9: 0x00000009
390 }
391}
3923 {
393 11: 0x0000000b
394 12: 0x000000000000000c
395 13: 1
396 14: "5"
397 15: "6"
398}
3994: "\000\001\002\003\374\377\377\377\377\377\377\377\377\001"
4005: 1"#
401 );
402 }
403
404 #[test]
405 fn fmt_unknown_group() {
406 let value = UnknownFieldSet::decode(b"\x0b\x0a\x03\x62\x61\x72\x0c\x13\x0a\x03\x66\x6f\x6f\x10\xfb\xff\xff\xff\xff\xff\xff\xff\xff\x01\x14\x1b\x0a\x00\x1c\x1b\x0a\x05\x68\x65\x6c\x6c\x6f\x10\x0a\x1c".as_ref()).unwrap();
407 assert_eq!(
408 fmt_unknown(&value),
409 r#"1{1:"bar"},2{1:"foo",2:18446744073709551611},3{1:""},3{1:"hello",2:10}"#
410 );
411 assert_eq!(
412 fmt_unknown_pretty(&value),
413 r#"1 {
414 1: "bar"
415}
4162 {
417 1: "foo"
418 2: 18446744073709551611
419}
4203 {
421 1: ""
422}
4233 {
424 1: "hello"
425 2: 10
426}"#
427 );
428 }
429
430 #[test]
431 fn fmt_include_default() {
432 let timestamp: prost_types::Timestamp = Default::default();
433 let message = timestamp.transcode_to_dynamic();
434
435 let mut string = String::new();
436 Writer::new(FormatOptions::new().skip_default_fields(false), &mut string)
437 .fmt_message(&message)
438 .unwrap();
439 assert_eq!(string, "seconds:0,nanos:0");
440 }
441}