prost_reflect/dynamic/text_format/
format.rs

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}