xCommonLib/serial/
api_descriptor.rs

1
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    // 存储所有 结构体的描述
23    pub message_descriptor_holder: HashMap<String, DescriptorProtoHolder>,
24
25    pub method_descriptor_map: HashMap<String, MethodDescriptorProto>,
26
27    // 所有枚举的 结构体描述
28    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            // msg_type.field
79            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        // 查询路径
133        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        //
143
144        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        //
198        Type::TYPE_FIXED64 | Type::TYPE_SFIXED64 | Type::TYPE_DOUBLE => WireType::Fixed64 as u32,
199        //
200        Type::TYPE_FIXED32 | Type::TYPE_SFIXED32 | Type::TYPE_FLOAT => WireType::Fixed32 as u32,
201        //
202        Type::TYPE_STRING | Type::TYPE_MESSAGE => WireType::LengthDelimited as u32,
203        //
204        _ => {
205            // let panic_str = format!("无法 识别 {} 类型", );
206            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; // 使用掩码0b111 (0x7) 获取 wire_type
216    let number = tag >> 3; // 将标签右移3位获取 number
217    (number, wire_type)
218}
219
220
221
222// 是否是 可选
223pub 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}