1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
extern crate protobuf;
extern crate serde_json;
use protobuf::Message;
use protobuf::descriptor::FieldDescriptorProto_Type;
use protobuf::reflect::FieldDescriptor;
#[cfg(test)]
mod tests;
pub fn proto_to_json(message: &dyn Message) -> serde_json::Value {
let mut map = serde_json::Map::new();
for field in message.descriptor().fields() {
match field_to_json(message, field) {
Some(x) => {
map.insert(field.name().to_string(), x)
},
None => continue
};
}
serde_json::Value::Object(map)
}
fn field_to_json(m: &dyn Message, fd: &FieldDescriptor) -> Option<serde_json::Value> {
if fd.is_repeated() {
match fd.len_field(m) {
0 => None,
_ => Some(repeated_field_to_json(m, fd)),
}
} else if fd.has_field(m) {
Some(singular_field_to_json(m, fd))
} else {
None
}
}
#[allow(dead_code)]
fn extract_vec_shim<'a, T>(
message: &'a dyn Message,
get_size_fn: &dyn Fn(&dyn Message) -> usize,
extract_one_fn: &dyn Fn(&'a dyn Message, usize) -> &'a T) -> Vec<&'a T> {
let size = get_size_fn(message);
let mut v = Vec::new();
for i in 0..size {
v.push(extract_one_fn(message, i));
}
v
}
fn repeated_entry_as_value(pbval: &dyn protobuf::reflect::ProtobufValue) -> serde_json::Value {
use protobuf::reflect::ProtobufValueRef;
use serde_json::Value;
use serde_json::Number;
match pbval.as_ref() {
ProtobufValueRef::Bool(x) => Value::Bool(x),
ProtobufValueRef::U32(x) => Value::Number(Number::from(x)),
ProtobufValueRef::U64(x) => Value::Number(Number::from(x)),
ProtobufValueRef::I32(x) => Value::Number(Number::from(x)),
ProtobufValueRef::I64(x) => Value::Number(Number::from(x)),
ProtobufValueRef::F32(x) => Value::Number(Number::from_f64(x as f64).expect("repeated f32")),
ProtobufValueRef::F64(x) => Value::Number(Number::from_f64(x).expect("repeated f64")),
ProtobufValueRef::Enum(x) => serde_json::Value::String(x.name().to_string()),
ProtobufValueRef::String(x) => serde_json::Value::String(x.to_string()),
ProtobufValueRef::Bytes(x) => serde_json::Value::String(std::str::from_utf8(x).expect("repeated bytes to string").to_string()),
ProtobufValueRef::Message(x) => proto_to_json(x),
}
}
fn repeated_field_to_json(message: &dyn Message,
field_descriptor: &FieldDescriptor) -> serde_json::Value {
match field_descriptor.get_reflect(message) {
protobuf::reflect::ReflectFieldRef::Repeated(rep_field) => {
return serde_json::Value::Array(
rep_field.into_iter().map(repeated_entry_as_value).collect());
},
_ => panic!("No repeated field"),
}
}
fn singular_field_to_json(message: &dyn protobuf::Message,
field_descriptor: &protobuf::reflect::FieldDescriptor) -> serde_json::Value {
match field_descriptor.proto().get_field_type() {
FieldDescriptorProto_Type::TYPE_DOUBLE => {
serde_json::Value::from(field_descriptor.get_f64(message))
},
FieldDescriptorProto_Type::TYPE_FLOAT => {
serde_json::Value::from(f64::from(field_descriptor.get_f32(message)))
},
FieldDescriptorProto_Type::TYPE_INT32 |
FieldDescriptorProto_Type::TYPE_SINT32 |
FieldDescriptorProto_Type::TYPE_SFIXED32 => {
serde_json::Value::from(i64::from(field_descriptor.get_i32(message)))
},
FieldDescriptorProto_Type::TYPE_INT64 |
FieldDescriptorProto_Type::TYPE_SINT64 |
FieldDescriptorProto_Type::TYPE_SFIXED64 => {
serde_json::Value::from(field_descriptor.get_i64(message))
},
FieldDescriptorProto_Type::TYPE_UINT32 |
FieldDescriptorProto_Type::TYPE_FIXED32 => {
serde_json::Value::from(u64::from(field_descriptor.get_u32(message)))
},
FieldDescriptorProto_Type::TYPE_UINT64 |
FieldDescriptorProto_Type::TYPE_FIXED64 => {
serde_json::Value::from(field_descriptor.get_u64(message))
},
FieldDescriptorProto_Type::TYPE_BOOL => {
serde_json::Value::Bool(field_descriptor.get_bool(message))
},
FieldDescriptorProto_Type::TYPE_STRING => {
serde_json::Value::String(field_descriptor.get_str(message).to_string())
},
FieldDescriptorProto_Type::TYPE_BYTES => {
serde_json::Value::String(
std::str::from_utf8(
field_descriptor.get_bytes(message)).unwrap().to_string())
},
FieldDescriptorProto_Type::TYPE_MESSAGE => {
let sub_message: &dyn protobuf::Message =
field_descriptor.get_message(message);
proto_to_json(sub_message)
},
FieldDescriptorProto_Type::TYPE_ENUM => {
serde_json::Value::String(
field_descriptor.get_enum(message).name().to_string())
},
FieldDescriptorProto_Type::TYPE_GROUP => unimplemented!(),
}
}