3Hren / msgpack-rust

MessagePack implementation for Rust / msgpack.org[Rust]
MIT License
1.13k stars 128 forks source link

What's the rust type for msgpack bin8 type? #280

Open tubzby opened 3 years ago

tubzby commented 3 years ago
    fn test_msgpack() {
        #[derive(Deserialize, Serialize, Debug)]
        struct A {
            a: Vec<u8>,
        }

        // 0x91: array of 1, 0xc4: bin8, 0x01: length, 0x48='H'
        let bs = vec![0x91, 0xc4, 0x01, 0x48];

        let mut de = Deserializer::new(&bs[..]);

        let a: A = Deserialize::deserialize(&mut de).unwrap();
    }

this test will fail with error: thread 'conn::conn::tests::test_msgpack' panicked at 'called Result::unwrap() on an Err value: Syntax("invalid type: byte array, expected a sequence")', src/conn/conn.rs:81:54.

kornelski commented 3 years ago

I don't know. It seems like it would be sensible to decode it to Vec, but maybe it's not supported?

tubzby commented 3 years ago

On my Golang server, I can encode it as fixstr or bin8, but none works on rust.

According to the msgpack spec, fixstr just means bytes array, not UTF8 string, in my opinion, we can both decode a fixstr to Vec and String.

tubzby commented 3 years ago

For anybody has the same problem, I have found a workaround by using: https://github.com/serde-rs/bytes. The encoding side still encode bytes array as fixstr, here's an example on decoding side:


    fn test_msgpack_decode() {
        #[derive(Deserialize, Serialize, Debug)]
        struct A {
            #[serde(with = "serde_bytes")]
            a: Vec<u8>,
        }

        // 0x91: array of 1, 0xc4: bin, 0x01: length
        // not working
        //let bs = vec![0x91, 0xc4, 0x01, 0x48];

        // array working
        //let bs = vec![0x91, 0x91, 0x48];

        // fix str
        let bs = vec![0x91, 0xa1, 0x48];

        let mut de = Deserializer::new(&bs[..]);

        let a: A = Deserialize::deserialize(&mut de).unwrap();
        println!("a is {:?}", a)
    }
ianhattendorf commented 1 year ago

https://docs.rs/serde_with/latest/serde_with/struct.Bytes.html seems to work for me for both decoding and encoding. Example struct:

use serde::{Deserialize, Serialize};
use serde_with::{serde_as, Bytes};

#[serde_as]
#[derive(Serialize, Deserialize, Debug)]
struct Foo {
  #[serde_as(as = "Bytes")]
  bar: Vec<u8>,
  #[serde_as(as = "Option<Bytes>")]
  baz: Option<Vec<u8>>
}