rustbinarymetadatagrpctonic

How to deserialize binary gRPC metadata to Rust struct?


Here's my codes.

#[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Metadata {
    /// login token
    #[prost(string, tag = "1")]
    pub access_key: ::prost::alloc::string::String,
    /// pack type
    #[prost(string, tag = "2")]
    pub mobi_app: ::prost::alloc::string::String,
    /// device
    #[prost(string, tag = "3")]
    pub device: ::prost::alloc::string::String,
    /// inner build id
    #[prost(int32, tag = "4")]
    pub build: i32,
    /// channel
    #[prost(string, tag = "5")]
    pub channel: ::prost::alloc::string::String,
    /// device buvid
    #[prost(string, tag = "6")]
    pub buvid: ::prost::alloc::string::String,
    /// app platform
    #[prost(string, tag = "7")]
    pub platform: ::prost::alloc::string::String,
}
//...
let req_metadata_bin = request
            .metadata()
            .get_bin("x-auth-metadata-bin")
            .unwrap()
            .as_ref();
let req_metadata: Metadata = bincode::deserialize(req_metadata_bin).unwrap();

I'm attempting to deserialize the binary gRPC metadata that comes from client. Someone told me to run the result thru bincode and deserialized into a struct, but I don't know exactly how to do so and wrote the codes above, obviously it don't work.

thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Custom { kind: UnexpectedEof, error: "" })'

I googled for solution but I got nothing. Any advice or code samples will help me a lot.

The binary data example:

x-auth-metadata-bin: CiA4NGIxOTE5NTUxZWM1ZGE5M2M1MzI4MzY5ODc5ZjNjMhIHYW5kcm9pZCD0oLADKgZtYXN0ZXIyJVhVMEQwNTgwQTgwQzgyMjc2RDlERjMzQjREMjA2NjVDNDJFMzM6B2FuZHJvaWQ

Solution

  • I assume that the following is your minimal reproducible example:

    #[derive(serde::Serialize, serde::Deserialize)]
    #[allow(clippy::derive_partial_eq_without_eq)]
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct Metadata {
        /// login token
        #[prost(string, tag = "1")]
        pub access_key: ::prost::alloc::string::String,
        /// pack type
        #[prost(string, tag = "2")]
        pub mobi_app: ::prost::alloc::string::String,
        /// device
        #[prost(string, tag = "3")]
        pub device: ::prost::alloc::string::String,
        /// inner build id
        #[prost(int32, tag = "4")]
        pub build: i32,
        /// channel
        #[prost(string, tag = "5")]
        pub channel: ::prost::alloc::string::String,
        /// device buvid
        #[prost(string, tag = "6")]
        pub buvid: ::prost::alloc::string::String,
        /// app platform
        #[prost(string, tag = "7")]
        pub platform: ::prost::alloc::string::String,
    }
    
    fn main() {
        let req_metadata_bin = base64::decode("CiA4NGIxOTE5NTUxZWM1ZGE5M2M1MzI4MzY5ODc5ZjNjMhIHYW5kcm9pZCD0oLADKgZtYXN0ZXIyJVhVMEQwNTgwQTgwQzgyMjc2RDlERjMzQjREMjA2NjVDNDJFMzM6B2FuZHJvaWQ=").unwrap();
        let req_metadata: Metadata = bincode::deserialize(&req_metadata_bin).unwrap();
        println!("{:#?}", req_metadata);
    }
    
    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Custom { kind: UnexpectedEof, error: "" })', src/main.rs:30:74
    

    bincode is a completely different format than ProtoBuf. To decode protobuf messages, you have to use an actual protobuf decoder.

    Like this:

    #[derive(serde::Serialize, serde::Deserialize)]
    #[allow(clippy::derive_partial_eq_without_eq)]
    #[derive(Clone, PartialEq, ::prost::Message)]
    pub struct Metadata {
        /// login token
        #[prost(string, tag = "1")]
        pub access_key: ::prost::alloc::string::String,
        /// pack type
        #[prost(string, tag = "2")]
        pub mobi_app: ::prost::alloc::string::String,
        /// device
        #[prost(string, tag = "3")]
        pub device: ::prost::alloc::string::String,
        /// inner build id
        #[prost(int32, tag = "4")]
        pub build: i32,
        /// channel
        #[prost(string, tag = "5")]
        pub channel: ::prost::alloc::string::String,
        /// device buvid
        #[prost(string, tag = "6")]
        pub buvid: ::prost::alloc::string::String,
        /// app platform
        #[prost(string, tag = "7")]
        pub platform: ::prost::alloc::string::String,
    }
    
    fn main() {
        let req_metadata_bin = base64::decode("CiA4NGIxOTE5NTUxZWM1ZGE5M2M1MzI4MzY5ODc5ZjNjMhIHYW5kcm9pZCD0oLADKgZtYXN0ZXIyJVhVMEQwNTgwQTgwQzgyMjc2RDlERjMzQjREMjA2NjVDNDJFMzM6B2FuZHJvaWQ=").unwrap();
        let req_metadata: Metadata = prost::Message::decode(req_metadata_bin.as_slice()).unwrap();
        println!("{:#?}", req_metadata);
    }
    
    Metadata {
        access_key: "84b1919551ec5da93c5328369879f3c2",
        mobi_app: "android",
        device: "",
        build: 7082100,
        channel: "master",
        buvid: "XU0D0580A80C82276D9DF33B4D20665C42E33",
        platform: "android",
    }