1extern crate protobuf;
2extern crate serde_json;
3
4use protobuf::Message;
5use protobuf::descriptor::FieldDescriptorProto_Type;
6use protobuf::reflect::FieldDescriptor;
7
8#[cfg(test)]
9mod tests;
10
11pub fn proto_to_json(message: &Message) -> serde_json::Value {
12 let mut map = serde_json::Map::new();
13
14 for field in message.descriptor().fields() {
15 match field_to_json(message, field) {
16 Some(x) => {
17 map.insert(field.name().to_string(), x)
18 },
19 None => continue
20 };
21 }
22 serde_json::Value::Object(map)
23}
24
25fn field_to_json(m: &Message, fd: &FieldDescriptor) -> Option<serde_json::Value> {
26 if fd.is_repeated() {
27 match fd.len_field(m) {
28 0 => None,
29 _ => Some(repeated_field_to_json(m, fd)),
30 }
31 } else if fd.has_field(m) {
32 Some(singular_field_to_json(m, fd))
33 } else {
34 None
35 }
36}
37
38#[allow(dead_code)]
43fn extract_vec_shim<'a, T>(
44 message: &'a Message,
45 get_size_fn: &Fn(&Message) -> usize,
46 extract_one_fn: &Fn(&'a Message, usize) -> &'a T) -> Vec<&'a T> {
47
48 let size = get_size_fn(message);
49 let mut v = Vec::new();
50 for i in 0..size {
51 v.push(extract_one_fn(message, i));
52 }
53 v
54}
55
56fn repeated_to_serde_array<T>(
57 message: &Message,
58 extract_fn: &Fn(&Message) -> Vec<T>,
59 convert_one_fn: &Fn(T) -> serde_json::Value) -> serde_json::Value {
60
61 serde_json::Value::Array(
62 extract_fn(message).into_iter().map(convert_one_fn).collect())
63}
64
65fn repeated_field_to_json(message: &Message,
66 field_descriptor: &FieldDescriptor) -> serde_json::Value {
67
68 match field_descriptor.proto().get_field_type() {
69 FieldDescriptorProto_Type::TYPE_DOUBLE => {
70 repeated_to_serde_array(
71 message,
72 &|m| field_descriptor.get_rep_f64(m).to_vec(),
73 &|v| serde_json::Value::from(v))
74 },
75 FieldDescriptorProto_Type::TYPE_FLOAT => {
76 repeated_to_serde_array(
77 message,
78 &|m| field_descriptor.get_rep_f32(m).to_vec(),
79 &|v| serde_json::Value::from(v))
80 },
81 FieldDescriptorProto_Type::TYPE_INT32 |
82 FieldDescriptorProto_Type::TYPE_SINT32 |
83 FieldDescriptorProto_Type::TYPE_SFIXED32 => {
84 repeated_to_serde_array(
85 message,
86 &|m| field_descriptor.get_rep_i32(m).to_vec(),
87 &|v| serde_json::Value::from(v))
88 },
89 FieldDescriptorProto_Type::TYPE_INT64 |
90 FieldDescriptorProto_Type::TYPE_SINT64 |
91 FieldDescriptorProto_Type::TYPE_SFIXED64 => {
92 repeated_to_serde_array(
93 message,
94 &|m| field_descriptor.get_rep_i64(m).to_vec(),
95 &|v| serde_json::Value::from(v))
96 },
97 FieldDescriptorProto_Type::TYPE_UINT32 |
98 FieldDescriptorProto_Type::TYPE_FIXED32 => {
99 repeated_to_serde_array(
100 message,
101 &|m| field_descriptor.get_rep_u32(m).to_vec(),
102 &|v| serde_json::Value::from(v))
103 },
104 FieldDescriptorProto_Type::TYPE_UINT64 |
105 FieldDescriptorProto_Type::TYPE_FIXED64 => {
106 repeated_to_serde_array(
107 message,
108 &|m| field_descriptor.get_rep_u64(m).to_vec(),
109 &|v| serde_json::Value::from(v))
110 },
111 FieldDescriptorProto_Type::TYPE_BOOL => {
112 repeated_to_serde_array(
113 message,
114 &|m| field_descriptor.get_rep_bool(m).to_vec(),
115 &serde_json::Value::Bool)
116 },
117 FieldDescriptorProto_Type::TYPE_STRING => {
118 repeated_to_serde_array(
119 message,
120 &|m| field_descriptor.get_rep_str(m).to_vec(),
121 &serde_json::Value::String)
122 },
123 FieldDescriptorProto_Type::TYPE_BYTES => {
124 repeated_to_serde_array(
125 message,
126 &|m| field_descriptor.get_rep_bytes(m).to_vec(),
127 &|v| serde_json::Value::String(std::str::from_utf8(&v).unwrap().to_string()))
128 },
129 FieldDescriptorProto_Type::TYPE_MESSAGE => {
130 let mut sub_messages: Vec<&protobuf::Message> = Vec::new();
131 for i in 0..field_descriptor.len_field(message) {
132 sub_messages.push(
133 field_descriptor.get_rep_message_item(message, i));
134 }
135
136 serde_json::Value::Array(sub_messages.into_iter().map(
137 |sub_message| proto_to_json(sub_message)).collect())
138
139 },
150 FieldDescriptorProto_Type::TYPE_ENUM => {
151 let mut enums = Vec::new();
152 for i in 0..field_descriptor.len_field(message) {
153 enums.push(field_descriptor.get_rep_enum_item(message, i));
154 }
155 serde_json::Value::Array(enums.into_iter().map(
156 |e| serde_json::Value::String(e.name().to_string())).collect())
157 },
158 FieldDescriptorProto_Type::TYPE_GROUP => unimplemented!(),
159 }
160}
161
162fn singular_field_to_json(message: &protobuf::Message,
163 field_descriptor: &protobuf::reflect::FieldDescriptor) -> serde_json::Value {
164 match field_descriptor.proto().get_field_type() {
165 FieldDescriptorProto_Type::TYPE_DOUBLE => {
166 serde_json::Value::from(field_descriptor.get_f64(message))
167 },
168 FieldDescriptorProto_Type::TYPE_FLOAT => {
169 serde_json::Value::from(f64::from(field_descriptor.get_f32(message)))
170 },
171 FieldDescriptorProto_Type::TYPE_INT32 |
172 FieldDescriptorProto_Type::TYPE_SINT32 |
173 FieldDescriptorProto_Type::TYPE_SFIXED32 => {
174 serde_json::Value::from(i64::from(field_descriptor.get_i32(message)))
175 },
176 FieldDescriptorProto_Type::TYPE_INT64 |
177 FieldDescriptorProto_Type::TYPE_SINT64 |
178 FieldDescriptorProto_Type::TYPE_SFIXED64 => {
179 serde_json::Value::from(field_descriptor.get_i64(message))
180 },
181 FieldDescriptorProto_Type::TYPE_UINT32 |
182 FieldDescriptorProto_Type::TYPE_FIXED32 => {
183 serde_json::Value::from(u64::from(field_descriptor.get_u32(message)))
184 },
185 FieldDescriptorProto_Type::TYPE_UINT64 |
186 FieldDescriptorProto_Type::TYPE_FIXED64 => {
187 serde_json::Value::from(field_descriptor.get_u64(message))
188 },
189 FieldDescriptorProto_Type::TYPE_BOOL => {
190 serde_json::Value::Bool(field_descriptor.get_bool(message))
191 },
192 FieldDescriptorProto_Type::TYPE_STRING => {
193 serde_json::Value::String(field_descriptor.get_str(message).to_string())
194 },
195 FieldDescriptorProto_Type::TYPE_BYTES => {
196 serde_json::Value::String(
197 std::str::from_utf8(
198 field_descriptor.get_bytes(message)).unwrap().to_string())
199 },
200 FieldDescriptorProto_Type::TYPE_MESSAGE => {
201 let sub_message: &protobuf::Message =
202 field_descriptor.get_message(message);
203 proto_to_json(sub_message)
204 },
205 FieldDescriptorProto_Type::TYPE_ENUM => {
206 serde_json::Value::String(
207 field_descriptor.get_enum(message).name().to_string())
208
209 },
210 FieldDescriptorProto_Type::TYPE_GROUP => unimplemented!(),
211 }
212}