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 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 fields.sort_by_key(|(field_number, _)| *field_number);
149 for (field_number, value) in fields {
150 print_field(
152 buf,
153 pretty,
154 indent,
155 &mut first,
156 field_number,
157 value.to_reflect_value_ref(),
158 );
159 }
160}
161
162pub 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
173pub fn print_to_string(m: &dyn MessageDyn) -> String {
175 print_to_string_internal(m, false)
176}
177
178pub fn print_to_string_pretty(m: &dyn MessageDyn) -> String {
180 print_to_string_internal(m, true)
181}
182
183pub 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}