• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::collections::HashMap;
2 
3 use crate::descriptor::EnumDescriptorProto;
4 use crate::descriptor::EnumValueDescriptorProto;
5 use crate::descriptor::FileDescriptorProto;
6 use crate::descriptorx::find_enum_by_rust_name;
7 use crate::reflect::find_message_or_enum::find_message_or_enum;
8 use crate::reflect::find_message_or_enum::MessageOrEnum;
9 use crate::ProtobufEnum;
10 
11 /// Description for enum variant.
12 ///
13 /// Used in reflection.
14 #[derive(Clone, Debug)]
15 pub struct EnumValueDescriptor {
16     proto: &'static EnumValueDescriptorProto,
17 }
18 
19 impl Copy for EnumValueDescriptor {}
20 
21 impl EnumValueDescriptor {
22     /// Name of enum variant as specified in proto file
name(&self) -> &'static str23     pub fn name(&self) -> &'static str {
24         self.proto.get_name()
25     }
26 
27     /// `i32` value of the enum variant
value(&self) -> i3228     pub fn value(&self) -> i32 {
29         self.proto.get_number()
30     }
31 }
32 
33 /// Dynamic representation of enum type.
34 ///
35 /// Can be used in reflective operations.
36 pub struct EnumDescriptor {
37     proto: &'static EnumDescriptorProto,
38     values: Vec<EnumValueDescriptor>,
39 
40     index_by_name: HashMap<String, usize>,
41     index_by_number: HashMap<i32, usize>,
42 }
43 
44 impl EnumDescriptor {
45     /// Enum name as given in `.proto` file
name(&self) -> &'static str46     pub fn name(&self) -> &'static str {
47         self.proto.get_name()
48     }
49 
50     /// `EnumDescriptor` for enum type
for_type<E: ProtobufEnum>() -> &'static EnumDescriptor51     pub fn for_type<E: ProtobufEnum>() -> &'static EnumDescriptor {
52         E::enum_descriptor_static()
53     }
54 
55     /// Create new enum descriptor.
56     ///
57     /// This function is called by generated code, and should not be called manually.
58     #[deprecated(
59         since = "2.12",
60         note = "Please regenerate .rs files from .proto files to use newer APIs"
61     )]
new(rust_name: &'static str, file: &'static FileDescriptorProto) -> EnumDescriptor62     pub fn new(rust_name: &'static str, file: &'static FileDescriptorProto) -> EnumDescriptor {
63         let proto = find_enum_by_rust_name(file, rust_name);
64         let mut index_by_name = HashMap::new();
65         let mut index_by_number = HashMap::new();
66         for (i, v) in proto.en.get_value().iter().enumerate() {
67             index_by_number.insert(v.get_number(), i);
68             index_by_name.insert(v.get_name().to_string(), i);
69         }
70         EnumDescriptor {
71             proto: proto.en,
72             values: proto
73                 .en
74                 .get_value()
75                 .iter()
76                 .map(|v| EnumValueDescriptor { proto: v })
77                 .collect(),
78             index_by_name: index_by_name,
79             index_by_number: index_by_number,
80         }
81     }
82 
83     /// Create new enum descriptor.
84     ///
85     /// This function is called by generated code, and should not be called manually.
new_pb_name<E>( name_in_file: &'static str, file: &'static FileDescriptorProto, ) -> EnumDescriptor where E: ProtobufEnum,86     pub fn new_pb_name<E>(
87         name_in_file: &'static str,
88         file: &'static FileDescriptorProto,
89     ) -> EnumDescriptor
90     where
91         E: ProtobufEnum,
92     {
93         let (_path_to_package, proto) = match find_message_or_enum(file, name_in_file) {
94             (path_to_package, MessageOrEnum::Enum(e)) => (path_to_package, e),
95             (_, MessageOrEnum::Message(_)) => panic!("not an enum"),
96         };
97 
98         let mut index_by_name = HashMap::new();
99         let mut index_by_number = HashMap::new();
100         for (i, v) in proto.get_value().iter().enumerate() {
101             index_by_number.insert(v.get_number(), i);
102             index_by_name.insert(v.get_name().to_string(), i);
103         }
104         EnumDescriptor {
105             proto,
106             values: proto
107                 .get_value()
108                 .iter()
109                 .map(|v| EnumValueDescriptor { proto: v })
110                 .collect(),
111             index_by_name: index_by_name,
112             index_by_number: index_by_number,
113         }
114     }
115 
116     /// Find enum value by name
value_by_name<'a>(&'a self, name: &str) -> &'a EnumValueDescriptor117     pub fn value_by_name<'a>(&'a self, name: &str) -> &'a EnumValueDescriptor {
118         // TODO: clone is weird
119         let &index = self.index_by_name.get(&name.to_string()).unwrap();
120         &self.values[index]
121     }
122 
123     /// Find enum value by number
value_by_number<'a>(&'a self, number: i32) -> &'a EnumValueDescriptor124     pub fn value_by_number<'a>(&'a self, number: i32) -> &'a EnumValueDescriptor {
125         let &index = self.index_by_number.get(&number).unwrap();
126         &self.values[index]
127     }
128 }
129