protobuf/reflect/
runtime_type_box.rs

1use std::fmt;
2
3use protobuf_support::lexer::float::parse_protobuf_float;
4use protobuf_support::lexer::str_lit::StrLit;
5
6use crate::descriptor::field_descriptor_proto;
7use crate::reflect::EnumDescriptor;
8use crate::reflect::MessageDescriptor;
9use crate::reflect::MessageRef;
10use crate::reflect::ReflectValueBox;
11use crate::reflect::ReflectValueRef;
12
13/// Runtime representation of elementary protobuf type.
14#[derive(Debug, Clone, Eq, PartialEq)]
15pub enum RuntimeType {
16    /// `i32`
17    I32,
18    /// `i64`
19    I64,
20    /// `u32`
21    U32,
22    /// `u64`
23    U64,
24    /// `f32`
25    F32,
26    /// `f64`
27    F64,
28    /// `bool`
29    Bool,
30    /// [`String`](std::string::String)
31    String,
32    /// [`Vec<u8>`](std::vec::Vec)
33    VecU8,
34    /// `enum`
35    Enum(EnumDescriptor),
36    /// `message`
37    Message(MessageDescriptor),
38}
39
40impl RuntimeType {
41    pub(crate) fn default_value_ref(&self) -> ReflectValueRef<'static> {
42        match self {
43            RuntimeType::I32 => ReflectValueRef::I32(0),
44            RuntimeType::I64 => ReflectValueRef::I64(0),
45            RuntimeType::U32 => ReflectValueRef::U32(0),
46            RuntimeType::U64 => ReflectValueRef::U64(0),
47            RuntimeType::F32 => ReflectValueRef::F32(0.0),
48            RuntimeType::F64 => ReflectValueRef::F64(0.0),
49            RuntimeType::Bool => ReflectValueRef::Bool(false),
50            RuntimeType::String => ReflectValueRef::String(""),
51            RuntimeType::VecU8 => ReflectValueRef::Bytes(b""),
52            RuntimeType::Enum(e) => ReflectValueRef::Enum(e.clone(), e.default_value().value()),
53            RuntimeType::Message(m) => ReflectValueRef::Message(MessageRef::default_instance(m)),
54        }
55    }
56
57    pub(crate) fn default_value_box(&self) -> ReflectValueBox {
58        self.default_value_ref().to_box()
59    }
60
61    /// Rust type from protobuf type.
62    ///
63    /// # Panics
64    ///
65    /// Panics for message or enum types (because they can't be resolved without context).
66    pub(crate) fn from_proto_type(t: field_descriptor_proto::Type) -> RuntimeType {
67        match t {
68            field_descriptor_proto::Type::TYPE_UINT32 => RuntimeType::U32,
69            field_descriptor_proto::Type::TYPE_UINT64 => RuntimeType::U64,
70            field_descriptor_proto::Type::TYPE_INT32 => RuntimeType::I32,
71            field_descriptor_proto::Type::TYPE_INT64 => RuntimeType::I64,
72            field_descriptor_proto::Type::TYPE_SINT32 => RuntimeType::I32,
73            field_descriptor_proto::Type::TYPE_SINT64 => RuntimeType::I64,
74            field_descriptor_proto::Type::TYPE_FIXED32 => RuntimeType::U32,
75            field_descriptor_proto::Type::TYPE_FIXED64 => RuntimeType::U64,
76            field_descriptor_proto::Type::TYPE_SFIXED64 => RuntimeType::I64,
77            field_descriptor_proto::Type::TYPE_SFIXED32 => RuntimeType::I32,
78            field_descriptor_proto::Type::TYPE_BOOL => RuntimeType::Bool,
79            field_descriptor_proto::Type::TYPE_STRING => RuntimeType::String,
80            field_descriptor_proto::Type::TYPE_BYTES => RuntimeType::VecU8,
81            field_descriptor_proto::Type::TYPE_FLOAT => RuntimeType::F32,
82            field_descriptor_proto::Type::TYPE_DOUBLE => RuntimeType::F64,
83            field_descriptor_proto::Type::TYPE_ENUM
84            | field_descriptor_proto::Type::TYPE_MESSAGE
85            | field_descriptor_proto::Type::TYPE_GROUP => panic!(
86                "{:?} cannot be converted to runtime type without context",
87                t
88            ),
89        }
90    }
91
92    pub(crate) fn parse_proto_default_value(&self, value: &str) -> Result<ReflectValueBox, ()> {
93        match self {
94            // For booleans, "true" or "false"
95            RuntimeType::Bool => {
96                if value == "true" {
97                    Ok(ReflectValueBox::Bool(true))
98                } else if value == "false" {
99                    Ok(ReflectValueBox::Bool(false))
100                } else {
101                    Err(())
102                }
103            }
104            RuntimeType::I32 => value.parse().map_err(|_| ()).map(ReflectValueBox::I32),
105            RuntimeType::I64 => value.parse().map_err(|_| ()).map(ReflectValueBox::I64),
106            RuntimeType::U32 => value.parse().map_err(|_| ()).map(ReflectValueBox::U32),
107            RuntimeType::U64 => value.parse().map_err(|_| ()).map(ReflectValueBox::U64),
108            RuntimeType::F32 => parse_protobuf_float(value)
109                .map_err(|_| ())
110                .map(|v| ReflectValueBox::F32(v as f32)),
111            RuntimeType::F64 => parse_protobuf_float(value)
112                .map_err(|_| ())
113                .map(ReflectValueBox::F64),
114            // For strings, contains the default text contents (not escaped in any way)
115            RuntimeType::String => Ok(ReflectValueBox::String(value.to_owned())),
116            // For bytes, contains the C escaped value.  All bytes >= 128 are escaped
117            RuntimeType::VecU8 => StrLit {
118                escaped: value.to_owned(),
119            }
120            .decode_bytes()
121            .map_err(|_| ())
122            .map(ReflectValueBox::Bytes),
123            RuntimeType::Enum(_) => {
124                // Handled outside.
125                Err(())
126            }
127            RuntimeType::Message(_) => {
128                // Message cannot have default value.
129                Err(())
130            }
131        }
132    }
133}
134
135impl fmt::Display for RuntimeType {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        match self {
138            RuntimeType::I32 => write!(f, "i32"),
139            RuntimeType::I64 => write!(f, "i64"),
140            RuntimeType::U32 => write!(f, "u32"),
141            RuntimeType::U64 => write!(f, "u64"),
142            RuntimeType::F32 => write!(f, "f32"),
143            RuntimeType::F64 => write!(f, "f64"),
144            RuntimeType::Bool => write!(f, "bool"),
145            RuntimeType::String => write!(f, "String"),
146            RuntimeType::VecU8 => write!(f, "Vec<u8>"),
147            RuntimeType::Enum(e) => write!(f, "{}", e.full_name()),
148            RuntimeType::Message(m) => write!(f, "{}", m.full_name()),
149        }
150    }
151}