protobuf/text_format/
print.rs

1use std::fmt;
2use std::fmt::Write;
3
4use protobuf_support::text_format::quote_bytes_to;
5
6use crate::message_dyn::MessageDyn;
7use crate::reflect::MessageRef;
8use crate::reflect::ReflectFieldRef;
9use crate::reflect::ReflectValueRef;
10use crate::UnknownValueRef;
11
12fn print_str_to(s: &str, buf: &mut String) {
13    // TODO: keep printable Unicode
14    quote_bytes_to(s.as_bytes(), buf);
15}
16
17fn do_indent(buf: &mut String, pretty: bool, indent: usize) {
18    if pretty && indent > 0 {
19        for _ in 0..indent {
20            buf.push_str("  ");
21        }
22    }
23}
24
25trait FieldName: fmt::Display {}
26impl<'a> FieldName for &'a str {}
27impl FieldName for u32 {}
28
29fn print_start_field<F: FieldName>(
30    buf: &mut String,
31    pretty: bool,
32    indent: usize,
33    first: &mut bool,
34    field_name: F,
35) {
36    if !*first && !pretty {
37        buf.push_str(" ");
38    }
39    do_indent(buf, pretty, indent);
40    *first = false;
41    write!(buf, "{}", field_name).unwrap();
42}
43
44fn print_end_field(buf: &mut String, pretty: bool) {
45    if pretty {
46        buf.push_str("\n");
47    }
48}
49
50fn print_field<F: FieldName>(
51    buf: &mut String,
52    pretty: bool,
53    indent: usize,
54    first: &mut bool,
55    field_name: F,
56    value: ReflectValueRef,
57) {
58    print_start_field(buf, pretty, indent, first, field_name);
59
60    match value {
61        ReflectValueRef::Message(m) => {
62            buf.push_str(" {");
63            if pretty {
64                buf.push_str("\n");
65            }
66            print_to_internal(&m, buf, pretty, indent + 1);
67            do_indent(buf, pretty, indent);
68            buf.push_str("}");
69        }
70        ReflectValueRef::Enum(d, v) => {
71            buf.push_str(": ");
72            match d.value_by_number(v) {
73                Some(e) => buf.push_str(e.name()),
74                None => write!(buf, ": {}", v).unwrap(),
75            }
76        }
77        ReflectValueRef::String(s) => {
78            buf.push_str(": ");
79            print_str_to(s, buf);
80        }
81        ReflectValueRef::Bytes(b) => {
82            buf.push_str(": ");
83            quote_bytes_to(b, buf);
84        }
85        ReflectValueRef::I32(v) => {
86            write!(buf, ": {}", v).unwrap();
87        }
88        ReflectValueRef::I64(v) => {
89            write!(buf, ": {}", v).unwrap();
90        }
91        ReflectValueRef::U32(v) => {
92            write!(buf, ": {}", v).unwrap();
93        }
94        ReflectValueRef::U64(v) => {
95            write!(buf, ": {}", v).unwrap();
96        }
97        ReflectValueRef::Bool(v) => {
98            write!(buf, ": {}", v).unwrap();
99        }
100        ReflectValueRef::F32(v) => {
101            write!(buf, ": {}", v).unwrap();
102        }
103        ReflectValueRef::F64(v) => {
104            write!(buf, ": {}", v).unwrap();
105        }
106    }
107
108    print_end_field(buf, pretty);
109}
110
111fn print_to_internal(m: &MessageRef, buf: &mut String, pretty: bool, indent: usize) {
112    let d = m.descriptor_dyn();
113    let mut first = true;
114    for f in d.fields() {
115        match f.get_reflect(&**m) {
116            ReflectFieldRef::Map(map) => {
117                for (k, v) in &map {
118                    print_start_field(buf, pretty, indent, &mut first, f.name());
119                    buf.push_str(" {");
120                    if pretty {
121                        buf.push_str("\n");
122                    }
123
124                    let mut entry_first = true;
125
126                    print_field(buf, pretty, indent + 1, &mut entry_first, "key", k);
127                    print_field(buf, pretty, indent + 1, &mut entry_first, "value", v);
128                    do_indent(buf, pretty, indent);
129                    buf.push_str("}");
130                    print_end_field(buf, pretty);
131                }
132            }
133            ReflectFieldRef::Repeated(repeated) => {
134                for v in repeated {
135                    print_field(buf, pretty, indent, &mut first, f.name(), v);
136                }
137            }
138            ReflectFieldRef::Optional(optional) => {
139                if let Some(v) = optional.value() {
140                    print_field(buf, pretty, indent, &mut first, f.name(), v);
141                }
142            }
143        }
144    }
145
146    let mut fields: Vec<(u32, UnknownValueRef)> = m.unknown_fields_dyn().iter().collect();
147    // Sort for stable output
148    fields.sort_by_key(|(field_number, _)| *field_number);
149    for (field_number, value) in fields {
150        // TODO: try decode nested message for length-delimited
151        print_field(
152            buf,
153            pretty,
154            indent,
155            &mut first,
156            field_number,
157            value.to_reflect_value_ref(),
158        );
159    }
160}
161
162/// Text-format
163pub fn print_to(m: &dyn MessageDyn, buf: &mut String) {
164    print_to_internal(&MessageRef::from(m), buf, false, 0)
165}
166
167fn print_to_string_internal(m: &dyn MessageDyn, pretty: bool) -> String {
168    let mut r = String::new();
169    print_to_internal(&MessageRef::from(m), &mut r, pretty, 0);
170    r
171}
172
173/// Text-format
174pub fn print_to_string(m: &dyn MessageDyn) -> String {
175    print_to_string_internal(m, false)
176}
177
178/// Text-format
179pub fn print_to_string_pretty(m: &dyn MessageDyn) -> String {
180    print_to_string_internal(m, true)
181}
182
183/// Text-format to `fmt::Formatter`.
184pub fn fmt(m: &dyn MessageDyn, f: &mut fmt::Formatter) -> fmt::Result {
185    let pretty = f.alternate();
186    f.write_str(&print_to_string_internal(m, pretty))
187}