在C++裏面, 咱們能夠根據一個消息的名稱, 動態的建立一個實例安全
google::protobuf::Descriptor* desc = google::protobuf::DescriptorPool::generated_pool() ->FindMessageTypeByName("mypkg.MyType"); google::protobuf::Message* message = google::protobuf::MessageFactory::generated_factory() ->GetPrototype(desc)->New();
這個在protobuf裏面是集成進去了, 在其餘語言也有相似的東西. ui
經過這個, 咱們就讓輕鬆實現編解碼庫, 而不需去構造一個映射表.this
可是, 可是在rust裏面, 是沒有這種東西的. 比較難的地方是rust全局變量必需要實現Send trait, 不然是不能被共享的, 這樣作確實安全, 可是對於咱們實現MessageFactory就變得困難.google
好在rust有thread_local和build.rs, 咱們能夠經過build.rs在編譯proto文件的時候去遍歷, 把每一個消息添加到一個thread_local的hash map裏面去, 從而曲線救國.spa
不說實現細節, 能夠本身去看源碼, 這邊說如何使用和集成.code
1. 建立一個子工程, 名字叫proto對象
而後將依賴添加進去:blog
[dependencies] protobuf = "2.8.0" [build-dependencies] protoc-rust = "2.8.0" protobuf_message_factory = "0.1.2"
2. 把全部的.proto文件都添加到src目錄下面去ip
3. 添加一個build.rs文件ci
extern crate protobuf_message_factory; use protobuf_message_factory::*; ... fn main() { let proto_path = "src/"; let proto_files = get_protos_info(proto_path); let proto_messages = get_proto_list(&proto_files); //!!! this is importent. !!! protoc_rust::run(protoc_rust::Args { out_dir: proto_path, input: &protos, includes: &[proto_path], customize: Customize { ..Default::default() }, }).expect("protoc"); //now generate factory codes generate_factory_file(proto_path, &proto_files); }
而後把build.rs添加到toml裏面去
4. 到主工程裏面去, 添加對proto工程的依賴
[dependencies] proto = {version="^0", path="proto"}
這時候, 就能夠在主工程裏面使用proto了
extern crate proto; use proto::factory::*; use proto::rpc::*; use local_ipaddress; fn main() { let desc = get_descriptor("mypkg.MyType".to_string()).unwrap(); println!("{}", desc.full_name()); let msg = desc.new_instance(); println!("msg: {:?}", msg); }
cargo run:
就能夠看到
mypkg.MyType
msg:
這時候就能夠拿到MessageDesriptor, 經過這個對象能夠new一個instance
倉庫在這裏https://crates.io/crates/protobuf_message_factory
關鍵字: MessageFactory, Protobuf, Rust