1 use std::fmt;
2 use std::fmt::Write;
3 
4 use protobuf_support::text_format::quote_bytes_to;
5 
6 use crate::message_dyn::MessageDyn;
7 use crate::reflect::MessageRef;
8 use crate::reflect::ReflectFieldRef;
9 use crate::reflect::ReflectValueRef;
10 use crate::UnknownValueRef;
11 
print_str_to(s: &str, buf: &mut String)12 fn print_str_to(s: &str, buf: &mut String) {
13     // TODO: keep printable Unicode
14     quote_bytes_to(s.as_bytes(), buf);
15 }
16 
do_indent(buf: &mut String, pretty: bool, indent: usize)17 fn 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 
25 trait FieldName: fmt::Display {}
26 impl<'a> FieldName for &'a str {}
27 impl FieldName for u32 {}
28 
print_start_field<F: FieldName>( buf: &mut String, pretty: bool, indent: usize, first: &mut bool, field_name: F, )29 fn 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 
print_end_field(buf: &mut String, pretty: bool)44 fn print_end_field(buf: &mut String, pretty: bool) {
45     if pretty {
46         buf.push_str("\n");
47     }
48 }
49 
print_field<F: FieldName>( buf: &mut String, pretty: bool, indent: usize, first: &mut bool, field_name: F, value: ReflectValueRef, )50 fn 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 
print_to_internal(m: &MessageRef, buf: &mut String, pretty: bool, indent: usize)111 fn 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
print_to(m: &dyn MessageDyn, buf: &mut String)163 pub fn print_to(m: &dyn MessageDyn, buf: &mut String) {
164     print_to_internal(&MessageRef::from(m), buf, false, 0)
165 }
166 
print_to_string_internal(m: &dyn MessageDyn, pretty: bool) -> String167 fn 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.to_string()
171 }
172 
173 /// Text-format
print_to_string(m: &dyn MessageDyn) -> String174 pub fn print_to_string(m: &dyn MessageDyn) -> String {
175     print_to_string_internal(m, false)
176 }
177 
178 /// Text-format
print_to_string_pretty(m: &dyn MessageDyn) -> String179 pub fn print_to_string_pretty(m: &dyn MessageDyn) -> String {
180     print_to_string_internal(m, true)
181 }
182 
183 /// Text-format to `fmt::Formatter`.
fmt(m: &dyn MessageDyn, f: &mut fmt::Formatter) -> fmt::Result184 pub 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 }
188