1 use std::fmt;
2 
3 use protobuf_support::lexer::float::parse_protobuf_float;
4 use protobuf_support::lexer::str_lit::StrLit;
5 
6 use crate::descriptor::field_descriptor_proto;
7 use crate::reflect::EnumDescriptor;
8 use crate::reflect::MessageDescriptor;
9 use crate::reflect::MessageRef;
10 use crate::reflect::ReflectValueBox;
11 use crate::reflect::ReflectValueRef;
12 
13 /// Runtime representation of elementary protobuf type.
14 #[derive(Debug, Clone, Eq, PartialEq)]
15 pub 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 
40 impl RuntimeType {
default_value_ref(&self) -> ReflectValueRef<'static>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 
default_value_box(&self) -> ReflectValueBox57     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).
from_proto_type(t: field_descriptor_proto::Type) -> RuntimeType66     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 
parse_proto_default_value(&self, value: &str) -> Result<ReflectValueBox, ()>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 
135 impl fmt::Display for RuntimeType {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result136     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 }
152