protobuf_json_temp/
lib.rs

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: &dyn 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: &dyn 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// Extracts a Vec<T> from a repeated proto field.
39// Most field types already have a function for extracting a Vec<T> directly,
40// however a few (e.g. Message) only have "len" and "get_item(i)" functions.
41// This function uses the len & get_item functions in order to create vector.
42#[allow(dead_code)]
43fn extract_vec_shim<'a, T>(
44    message: &'a dyn Message,
45    get_size_fn: &dyn Fn(&dyn Message) -> usize,
46    extract_one_fn: &dyn Fn(&'a dyn 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_entry_as_value(pbval: &dyn protobuf::reflect::ProtobufValue) -> serde_json::Value {
57    use protobuf::reflect::ProtobufValueRef;
58    use serde_json::Value;
59    use serde_json::Number;
60
61    // |x: &dyn protobuf::reflect::ProtobufValue| serde_json::Value::from(x)
62    match pbval.as_ref() {
63        ProtobufValueRef::Bool(x) => Value::Bool(x),
64        ProtobufValueRef::U32(x) => Value::Number(Number::from(x)),
65        ProtobufValueRef::U64(x) => Value::Number(Number::from(x)),
66        ProtobufValueRef::I32(x) => Value::Number(Number::from(x)),
67        ProtobufValueRef::I64(x) => Value::Number(Number::from(x)),
68        ProtobufValueRef::F32(x) => Value::Number(Number::from_f64(x as f64).expect("repeated f32")),
69        ProtobufValueRef::F64(x) => Value::Number(Number::from_f64(x).expect("repeated f64")),
70        ProtobufValueRef::Enum(x) => serde_json::Value::String(x.name().to_string()),
71        ProtobufValueRef::String(x) => serde_json::Value::String(x.to_string()),
72        ProtobufValueRef::Bytes(x) => serde_json::Value::String(std::str::from_utf8(x).expect("repeated bytes to string").to_string()),
73        ProtobufValueRef::Message(x) => proto_to_json(x),
74    }
75}
76
77fn repeated_field_to_json(message: &dyn Message,
78                          field_descriptor: &FieldDescriptor) -> serde_json::Value {
79
80
81    match field_descriptor.get_reflect(message) {
82        // rep_field is a "&dyn protobuf::reflect::repeated::ReflectRepeatedRef"
83        protobuf::reflect::ReflectFieldRef::Repeated(rep_field) => {
84            return serde_json::Value::Array(
85                rep_field.into_iter().map(repeated_entry_as_value).collect());
86        },
87        _ => panic!("No repeated field"),
88    }
89
90}
91
92fn singular_field_to_json(message: &dyn protobuf::Message,
93                          field_descriptor: &protobuf::reflect::FieldDescriptor) -> serde_json::Value {
94    match field_descriptor.proto().get_field_type() {
95        FieldDescriptorProto_Type::TYPE_DOUBLE => {
96            serde_json::Value::from(field_descriptor.get_f64(message))
97        },
98        FieldDescriptorProto_Type::TYPE_FLOAT => {
99            serde_json::Value::from(f64::from(field_descriptor.get_f32(message)))
100        },
101        FieldDescriptorProto_Type::TYPE_INT32 |
102        FieldDescriptorProto_Type::TYPE_SINT32 |
103        FieldDescriptorProto_Type::TYPE_SFIXED32 => {
104            serde_json::Value::from(i64::from(field_descriptor.get_i32(message)))
105        },
106        FieldDescriptorProto_Type::TYPE_INT64 |
107        FieldDescriptorProto_Type::TYPE_SINT64 |
108        FieldDescriptorProto_Type::TYPE_SFIXED64 => {
109            serde_json::Value::from(field_descriptor.get_i64(message))
110        },
111        FieldDescriptorProto_Type::TYPE_UINT32 |
112        FieldDescriptorProto_Type::TYPE_FIXED32 => {
113            serde_json::Value::from(u64::from(field_descriptor.get_u32(message)))
114        },
115        FieldDescriptorProto_Type::TYPE_UINT64 |
116        FieldDescriptorProto_Type::TYPE_FIXED64 => {
117            serde_json::Value::from(field_descriptor.get_u64(message))
118        },
119        FieldDescriptorProto_Type::TYPE_BOOL => {
120            serde_json::Value::Bool(field_descriptor.get_bool(message))
121        },
122        FieldDescriptorProto_Type::TYPE_STRING => {
123            serde_json::Value::String(field_descriptor.get_str(message).to_string())
124        },
125        FieldDescriptorProto_Type::TYPE_BYTES => {
126            serde_json::Value::String(
127                std::str::from_utf8(
128                    field_descriptor.get_bytes(message)).unwrap().to_string())
129        },
130        FieldDescriptorProto_Type::TYPE_MESSAGE => {
131            let sub_message: &dyn protobuf::Message =
132                field_descriptor.get_message(message);
133            proto_to_json(sub_message)
134        },
135        FieldDescriptorProto_Type::TYPE_ENUM => {
136            serde_json::Value::String(
137                field_descriptor.get_enum(message).name().to_string())
138
139        },
140        FieldDescriptorProto_Type::TYPE_GROUP => unimplemented!(),
141    }
142}