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