x-common-lib 0.1.8

DXMesh rust dxc develop library
Documentation

use protobuf::descriptor::field_descriptor_proto::{Label, Type};
use protobuf::descriptor::{
    DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, MethodDescriptorProto,
    ServiceDescriptorProto,
};

use protobuf::rt::WireType;

use protobuf::Enum;
use protobuf_parse::Parser;
use std::collections::HashMap;
use tracing::warn;

pub struct DescriptorProtoHolder {
    pub descriptor_proto: DescriptorProto,
    pub field_index_map: HashMap<u32, u32>,
}

pub struct ServiceApiDescriptor {
    pub service_descriptor: ServiceDescriptorProto,
    // 存储所有 结构体的描述
    pub message_descriptor_holder: HashMap<String, DescriptorProtoHolder>,

    pub method_descriptor_map: HashMap<String, MethodDescriptorProto>,

    // 所有枚举的 结构体描述
    pub enum_descriptor_map: HashMap<String, EnumDescriptorProto>,
}

impl ServiceApiDescriptor {
    pub fn service_name(&self) -> &str {
        self.service_descriptor.name()
    }

    pub fn methods(&self) -> &Vec<MethodDescriptorProto> {
        &self.service_descriptor.method
    }

    pub fn method(&self, method_name: &str) -> Option<&MethodDescriptorProto> {
        self.method_descriptor_map.get(method_name)
    }

    pub fn get_message_descriptor(&self, message_name: &str) -> Option<&DescriptorProto> {
        let holder = self.message_descriptor_holder.get(message_name);

        if holder.is_none() {
            return None;
        }

        let holder = holder.unwrap();

        Some(&holder.descriptor_proto)
    }

    fn put_enum_descriptor_in_map(
        scope: &str,
        enum_types: &Vec<EnumDescriptorProto>,
        enum_descriptor_map: &mut HashMap<String, EnumDescriptorProto>,
    ) {
        for enum_type in enum_types {
            let enum_name = enum_type.name();
            let key_name = format!("{}{}", scope, enum_name);
            enum_descriptor_map.insert(key_name, enum_type.clone());
        }
    }

    fn put_message_descriptor_in_map(
        scope: &str,
        message_types: &Vec<DescriptorProto>,
        service_api_descriptor: &mut ServiceApiDescriptor,
    ) {
        for msg_type in message_types {
            let msg_name = msg_type.name();
            let key_name = format!("{}{}", scope, msg_name);
            let new_scope = format!("{}.", key_name);
            let mut field_index_map: HashMap<u32, u32> = HashMap::new();
            // msg_type.field
            let mut cur_index: u32 = 0;

            for field in &msg_type.field {
                let number = field.number.unwrap();

                let wire_type = get_wire_type(field);

                let tag = make_tag(number as u32, wire_type);

                field_index_map.insert(tag, cur_index);

                cur_index += 1;
            }

            service_api_descriptor.message_descriptor_holder.insert(
                key_name,
                DescriptorProtoHolder {
                    descriptor_proto: msg_type.clone(),
                    field_index_map,
                },
            );

            Self::put_message_descriptor_in_map(
                &new_scope,
                &msg_type.nested_type,
                service_api_descriptor,
            );

            Self::put_enum_descriptor_in_map(
                &new_scope,
                &msg_type.enum_type,
                &mut service_api_descriptor.enum_descriptor_map,
            );
        }
    }

    pub fn load(proto_file_path: &str) -> Result<ServiceApiDescriptor, String> {
        Self::load_with_include_path(proto_file_path, ".", true)
    }

    pub fn load_with_include_path(
        proto_file_path: &str,
        include_path: &str,
        check_service: bool,
    ) -> Result<ServiceApiDescriptor, String> {
        let mut ins = ServiceApiDescriptor {
            message_descriptor_holder: HashMap::new(),
            method_descriptor_map: HashMap::new(),
            service_descriptor: ServiceDescriptorProto::default(),
            enum_descriptor_map: HashMap::new(),
        };
        let mut parser = Parser::new();
        parser.pure();
        // 查询路径
        parser.include(include_path);
        parser.inputs(&[proto_file_path]);

        let file_desc_set = parser.file_descriptor_set();
        if file_desc_set.is_err() {
            warn!("加载描述文件:{} 失败", proto_file_path);
            return Err(format!("解析描述文件失败:{}", file_desc_set.err().unwrap()));
        }
        let file_desc_set = file_desc_set.unwrap();
        //

        let file_descriptor = file_desc_set.file.get(0);
        if file_descriptor.is_none() {
            warn!("加载描述文件:{} 失败", proto_file_path);
            return Err(format!("解析描述文件失败, 描述文件不存在!"));
        }

        let file_descriptor = file_descriptor.unwrap();

        if check_service {
            let service = &file_descriptor.service;

            if service.len() != 1 {
                warn!(
                    "描述文件{}错误:描述文件只能由一个 Service 描述",
                    proto_file_path
                );
                return Err("描述文件错误:描述文件只能由一个 Service 描述".into());

            }
            let service: &ServiceDescriptorProto = service.get(0).unwrap();

            ins.service_descriptor = service.clone();

            for method in ins.service_descriptor.method.iter() {
                ins.method_descriptor_map
                    .insert(String::from(method.name()), method.clone());
            }
        }

        Self::put_message_descriptor_in_map(".", &file_descriptor.message_type, &mut ins);

        Self::put_enum_descriptor_in_map(
            ".",
            &file_descriptor.enum_type,
            &mut ins.enum_descriptor_map,
        );

        Ok(ins)
    }
}

pub fn get_wire_type(field: &FieldDescriptorProto) -> u32 {
    let field_type = field.type_.unwrap().unwrap();

    match field_type {
        Type::TYPE_INT64
        | Type::TYPE_UINT64
        | Type::TYPE_INT32
        | Type::TYPE_UINT32
        | Type::TYPE_ENUM
        | Type::TYPE_SINT32
        | Type::TYPE_SINT64
        | Type::TYPE_BOOL => WireType::Varint as u32,
        //
        Type::TYPE_FIXED64 | Type::TYPE_SFIXED64 | Type::TYPE_DOUBLE => WireType::Fixed64 as u32,
        //
        Type::TYPE_FIXED32 | Type::TYPE_SFIXED32 | Type::TYPE_FLOAT => WireType::Fixed32 as u32,
        //
        Type::TYPE_STRING | Type::TYPE_MESSAGE => WireType::LengthDelimited as u32,
        //
        _ => {
            // let panic_str = format!("无法 识别 {} 类型", );
            panic!("无法 识别 {} 类型", field.name.as_ref().unwrap())
        }
    }
}

pub fn make_tag(number: u32, wire_type: u32) -> u32 {
    (number << 3) | wire_type
}
pub fn tag_to_number_and_wire_type(tag: u32) -> (u32, u32) {
    let wire_type = tag & 0b111; // 使用掩码0b111 (0x7) 获取 wire_type
    let number = tag >> 3; // 将标签右移3位获取 number
    (number, wire_type)
}



// 是否是 可选
pub fn is_optional(field: &FieldDescriptorProto) -> bool {
    return if field.proto3_optional.is_some() {
        field.proto3_optional.unwrap()
    } else {
        false
    };
}

pub fn is_integer(field: &FieldDescriptorProto) -> bool {
    if let Some(type_value) = field.type_ {
        let type_value = type_value.value();
        type_value == Type::TYPE_INT64.value()
            || type_value == Type::TYPE_UINT64.value()
            || type_value == Type::TYPE_INT32.value()
            || type_value == Type::TYPE_FIXED64.value()
            || type_value == Type::TYPE_FIXED32.value()
            || type_value == Type::TYPE_UINT32.value()
            || type_value == Type::TYPE_ENUM.value()
            || type_value == Type::TYPE_SFIXED32.value()
            || type_value == Type::TYPE_SFIXED64.value()
            || type_value == Type::TYPE_SINT32.value()
            || type_value == Type::TYPE_SINT64.value()
    } else {
        false
    }
}

pub fn is_float(field: &FieldDescriptorProto) -> bool {
    if let Some(type_value) = field.type_ {
        let type_value = type_value.value();
        type_value == Type::TYPE_DOUBLE.value() || type_value == Type::TYPE_FLOAT.value()
    } else {
        false
    }
}

pub fn is_string(field: &FieldDescriptorProto) -> bool {
    if let Some(type_value) = field.type_ {
        let type_value = type_value.value();
        type_value == Type::TYPE_STRING.value()
    } else {
        false
    }
}

pub fn is_object(field: &FieldDescriptorProto) -> bool {
    if let Some(type_value) = field.type_ {
        type_value.value() == Type::TYPE_MESSAGE.value()
    } else {
        false
    }
}

pub fn is_message_or_enum(field: &FieldDescriptorProto) -> bool {
    let field_type = field.type_.unwrap().unwrap();
    match field_type {
        Type::TYPE_MESSAGE | Type::TYPE_ENUM => true,
        _ => false,
    }
}

pub fn is_array(field: &FieldDescriptorProto) -> bool {
    if let Some(label) = field.label {
        label.value() == Label::LABEL_REPEATED.value()
    } else {
        false
    }
}

pub fn is_map(field: &FieldDescriptorProto, api_descriptor: &ServiceApiDescriptor) -> bool {
    if let Some(type_name) = &field.type_name {
        let message_descriptor = api_descriptor.get_message_descriptor(type_name);

        if message_descriptor.is_none() {
            return false;
        }
        let message_descriptor = message_descriptor.unwrap();

        return message_descriptor.options.map_entry();
    }

    false
}