xCommonLib/serial/
api_descriptor.rs1
2use protobuf::descriptor::field_descriptor_proto::{Label, Type};
3use protobuf::descriptor::{
4 DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, MethodDescriptorProto,
5 ServiceDescriptorProto,
6};
7
8use protobuf::rt::WireType;
9
10use protobuf::Enum;
11use protobuf_parse::Parser;
12use std::collections::HashMap;
13use tracing::warn;
14
15pub struct DescriptorProtoHolder {
16 pub descriptor_proto: DescriptorProto,
17 pub field_index_map: HashMap<u32, u32>,
18}
19
20pub struct ServiceApiDescriptor {
21 pub service_descriptor: ServiceDescriptorProto,
22 pub message_descriptor_holder: HashMap<String, DescriptorProtoHolder>,
24
25 pub method_descriptor_map: HashMap<String, MethodDescriptorProto>,
26
27 pub enum_descriptor_map: HashMap<String, EnumDescriptorProto>,
29}
30
31impl ServiceApiDescriptor {
32 pub fn service_name(&self) -> &str {
33 self.service_descriptor.name()
34 }
35
36 pub fn methods(&self) -> &Vec<MethodDescriptorProto> {
37 &self.service_descriptor.method
38 }
39
40 pub fn method(&self, method_name: &str) -> Option<&MethodDescriptorProto> {
41 self.method_descriptor_map.get(method_name)
42 }
43
44 pub fn get_message_descriptor(&self, message_name: &str) -> Option<&DescriptorProto> {
45 let holder = self.message_descriptor_holder.get(message_name);
46
47 if holder.is_none() {
48 return None;
49 }
50
51 let holder = holder.unwrap();
52
53 Some(&holder.descriptor_proto)
54 }
55
56 fn put_enum_descriptor_in_map(
57 scope: &str,
58 enum_types: &Vec<EnumDescriptorProto>,
59 enum_descriptor_map: &mut HashMap<String, EnumDescriptorProto>,
60 ) {
61 for enum_type in enum_types {
62 let enum_name = enum_type.name();
63 let key_name = format!("{}{}", scope, enum_name);
64 enum_descriptor_map.insert(key_name, enum_type.clone());
65 }
66 }
67
68 fn put_message_descriptor_in_map(
69 scope: &str,
70 message_types: &Vec<DescriptorProto>,
71 service_api_descriptor: &mut ServiceApiDescriptor,
72 ) {
73 for msg_type in message_types {
74 let msg_name = msg_type.name();
75 let key_name = format!("{}{}", scope, msg_name);
76 let new_scope = format!("{}.", key_name);
77 let mut field_index_map: HashMap<u32, u32> = HashMap::new();
78 let mut cur_index: u32 = 0;
80
81 for field in &msg_type.field {
82 let number = field.number.unwrap();
83
84 let wire_type = get_wire_type(field);
85
86 let tag = make_tag(number as u32, wire_type);
87
88 field_index_map.insert(tag, cur_index);
89
90 cur_index += 1;
91 }
92
93 service_api_descriptor.message_descriptor_holder.insert(
94 key_name,
95 DescriptorProtoHolder {
96 descriptor_proto: msg_type.clone(),
97 field_index_map,
98 },
99 );
100
101 Self::put_message_descriptor_in_map(
102 &new_scope,
103 &msg_type.nested_type,
104 service_api_descriptor,
105 );
106
107 Self::put_enum_descriptor_in_map(
108 &new_scope,
109 &msg_type.enum_type,
110 &mut service_api_descriptor.enum_descriptor_map,
111 );
112 }
113 }
114
115 pub fn load(proto_file_path: &str) -> Result<ServiceApiDescriptor, String> {
116 Self::load_with_include_path(proto_file_path, ".", true)
117 }
118
119 pub fn load_with_include_path(
120 proto_file_path: &str,
121 include_path: &str,
122 check_service: bool,
123 ) -> Result<ServiceApiDescriptor, String> {
124 let mut ins = ServiceApiDescriptor {
125 message_descriptor_holder: HashMap::new(),
126 method_descriptor_map: HashMap::new(),
127 service_descriptor: ServiceDescriptorProto::default(),
128 enum_descriptor_map: HashMap::new(),
129 };
130 let mut parser = Parser::new();
131 parser.pure();
132 parser.include(include_path);
134 parser.inputs(&[proto_file_path]);
135
136 let file_desc_set = parser.file_descriptor_set();
137 if file_desc_set.is_err() {
138 warn!("加载描述文件:{} 失败", proto_file_path);
139 return Err(format!("解析描述文件失败:{}", file_desc_set.err().unwrap()));
140 }
141 let file_desc_set = file_desc_set.unwrap();
142 let file_descriptor = file_desc_set.file.get(0);
145 if file_descriptor.is_none() {
146 warn!("加载描述文件:{} 失败", proto_file_path);
147 return Err(format!("解析描述文件失败, 描述文件不存在!"));
148 }
149
150 let file_descriptor = file_descriptor.unwrap();
151
152 if check_service {
153 let service = &file_descriptor.service;
154
155 if service.len() != 1 {
156 warn!(
157 "描述文件{}错误:描述文件只能由一个 Service 描述",
158 proto_file_path
159 );
160 return Err("描述文件错误:描述文件只能由一个 Service 描述".into());
161
162 }
163 let service: &ServiceDescriptorProto = service.get(0).unwrap();
164
165 ins.service_descriptor = service.clone();
166
167 for method in ins.service_descriptor.method.iter() {
168 ins.method_descriptor_map
169 .insert(String::from(method.name()), method.clone());
170 }
171 }
172
173 Self::put_message_descriptor_in_map(".", &file_descriptor.message_type, &mut ins);
174
175 Self::put_enum_descriptor_in_map(
176 ".",
177 &file_descriptor.enum_type,
178 &mut ins.enum_descriptor_map,
179 );
180
181 Ok(ins)
182 }
183}
184
185pub fn get_wire_type(field: &FieldDescriptorProto) -> u32 {
186 let field_type = field.type_.unwrap().unwrap();
187
188 match field_type {
189 Type::TYPE_INT64
190 | Type::TYPE_UINT64
191 | Type::TYPE_INT32
192 | Type::TYPE_UINT32
193 | Type::TYPE_ENUM
194 | Type::TYPE_SINT32
195 | Type::TYPE_SINT64
196 | Type::TYPE_BOOL => WireType::Varint as u32,
197 Type::TYPE_FIXED64 | Type::TYPE_SFIXED64 | Type::TYPE_DOUBLE => WireType::Fixed64 as u32,
199 Type::TYPE_FIXED32 | Type::TYPE_SFIXED32 | Type::TYPE_FLOAT => WireType::Fixed32 as u32,
201 Type::TYPE_STRING | Type::TYPE_MESSAGE => WireType::LengthDelimited as u32,
203 _ => {
205 panic!("无法 识别 {} 类型", field.name.as_ref().unwrap())
207 }
208 }
209}
210
211pub fn make_tag(number: u32, wire_type: u32) -> u32 {
212 (number << 3) | wire_type
213}
214pub fn tag_to_number_and_wire_type(tag: u32) -> (u32, u32) {
215 let wire_type = tag & 0b111; let number = tag >> 3; (number, wire_type)
218}
219
220
221
222pub fn is_optional(field: &FieldDescriptorProto) -> bool {
224 return if field.proto3_optional.is_some() {
225 field.proto3_optional.unwrap()
226 } else {
227 false
228 };
229}
230
231pub fn is_integer(field: &FieldDescriptorProto) -> bool {
232 if let Some(type_value) = field.type_ {
233 let type_value = type_value.value();
234 type_value == Type::TYPE_INT64.value()
235 || type_value == Type::TYPE_UINT64.value()
236 || type_value == Type::TYPE_INT32.value()
237 || type_value == Type::TYPE_FIXED64.value()
238 || type_value == Type::TYPE_FIXED32.value()
239 || type_value == Type::TYPE_UINT32.value()
240 || type_value == Type::TYPE_ENUM.value()
241 || type_value == Type::TYPE_SFIXED32.value()
242 || type_value == Type::TYPE_SFIXED64.value()
243 || type_value == Type::TYPE_SINT32.value()
244 || type_value == Type::TYPE_SINT64.value()
245 } else {
246 false
247 }
248}
249
250pub fn is_float(field: &FieldDescriptorProto) -> bool {
251 if let Some(type_value) = field.type_ {
252 let type_value = type_value.value();
253 type_value == Type::TYPE_DOUBLE.value() || type_value == Type::TYPE_FLOAT.value()
254 } else {
255 false
256 }
257}
258
259pub fn is_string(field: &FieldDescriptorProto) -> bool {
260 if let Some(type_value) = field.type_ {
261 let type_value = type_value.value();
262 type_value == Type::TYPE_STRING.value()
263 } else {
264 false
265 }
266}
267
268pub fn is_object(field: &FieldDescriptorProto) -> bool {
269 if let Some(type_value) = field.type_ {
270 type_value.value() == Type::TYPE_MESSAGE.value()
271 } else {
272 false
273 }
274}
275
276pub fn is_message_or_enum(field: &FieldDescriptorProto) -> bool {
277 let field_type = field.type_.unwrap().unwrap();
278 match field_type {
279 Type::TYPE_MESSAGE | Type::TYPE_ENUM => true,
280 _ => false,
281 }
282}
283
284pub fn is_array(field: &FieldDescriptorProto) -> bool {
285 if let Some(label) = field.label {
286 label.value() == Label::LABEL_REPEATED.value()
287 } else {
288 false
289 }
290}
291
292pub fn is_map(field: &FieldDescriptorProto, api_descriptor: &ServiceApiDescriptor) -> bool {
293 if let Some(type_name) = &field.type_name {
294 let message_descriptor = api_descriptor.get_message_descriptor(type_name);
295
296 if message_descriptor.is_none() {
297 return false;
298 }
299 let message_descriptor = message_descriptor.unwrap();
300
301 return message_descriptor.options.map_entry();
302 }
303
304 false
305}