bincode-org / bincode

A binary encoder / decoder implementation in Rust.
MIT License
2.63k stars 265 forks source link

Add note about Maps to readme #697

Closed c-git closed 4 months ago

c-git commented 6 months ago

Hi,

Thanks you very much really great crate. I understand why maps cannot be supported and it makes sense but it's not really mentioned in the readme or anywhere that I checked (only checked the readme and I the first page on docs.rs). Might be good to mention it so beginners don't get tripped up. Let me know if that's ok and I can do the PR or feel free to say it in your own way.

VictorKoenders commented 6 months ago

Which maps are not supported? If it's in the standard library I think we should be able to support it

c-git commented 5 months ago

I'll try to produce an example. IIRC it was a BTreeMap from std. But I will double check and get back to you on this.

c-git commented 5 months ago

Works now with suggestion from https://github.com/bincode-org/bincode/issues/697#issuecomment-2088143191

Old Text of comment

I tried to use the example in the readme to make the example of the map but I can't quite get it to compile. I'm not sure what I'm doing wrong. I converted it into a single file script to show the dependencies that I assumed. I'm not sure if the API has changed or if I'm doing something wrong. Will try to create the example without using the sample.

Fixed code

#!/usr/bin/env -S cargo +nightly -Zscript
```cargo
package.edition = "2021"
# dependencies.bincode = "1.3.3" # doesn't work with this version.
dependencies.bincode = "2.0.0-rc"

use bincode::{config, Decode, Encode};

[derive(Encode, Decode, PartialEq, Debug)]

struct Entity { x: f32, y: f32, }

[derive(Encode, Decode, PartialEq, Debug)]

struct World(Vec);

fn main() { let config = config::standard();

let world = World(vec![Entity { x: 0.0, y: 4.0 }, Entity { x: 10.0, y: 20.5 }]);

let encoded: Vec<u8> = bincode::encode_to_vec(&world, config).unwrap();

// The length of the vector is encoded as a varint u64, which in this case gets collapsed to a single byte
// See the documentation on varint for more info for that.
// The 4 floats are encoded in 4 bytes each.
assert_eq!(encoded.len(), 1 + 4 * 4);

let (decoded, len): (World, usize) = bincode::decode_from_slice(&encoded[..], config).unwrap();

assert_eq!(world, decoded);
assert_eq!(len, encoded.len()); // read all bytes

}

c-git commented 5 months ago

I created a test case using a map and found no problem so I must have had an incorrect root cause analysis when I came to this conclusion. My apologies for creating this issue without creating a MRE to show the problem. I don't recall what the issue was but I recall being short on time and creating this to help the next person but seems I may have just mislead people instead of helping. Again my apologies. My example with a map that worked for the next person looking at this can be found below.

#!/usr/bin/env -S cargo +nightly -Zscript
```cargo
package.edition = "2021"

[dependencies]
bincode = "1.3.3"
serde = { version = "1.0.197", features = ["derive"] }

use std::collections::BTreeMap;

[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]

struct Entity { x: f32, y: f32, other: BTreeMap<i32, i32>, }

[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]

struct World(Vec);

fn main() { let mut other = BTreeMap::new(); other.insert(3, 4); other.insert(5, 6);

// The object that we will serialize.
let target: Option<World> = Some(World(vec![Entity {
    x: 1.,
    y: 2.,
    other,
}]));

let encoded: Vec<u8> = bincode::serialize(&target).unwrap();
let decoded: Option<World> = bincode::deserialize(&encoded[..]).unwrap();
assert_eq!(target, decoded);

}

c-git commented 5 months ago

I'm not sure if the issue with not being able to compile the example https://github.com/bincode-org/bincode/issues/697#issuecomment-2028486684 from the readme is valid and if I should create a separate issue for it as this one should be closed as it wasn't valid.

VictorKoenders commented 4 months ago

Oh I just realized why the example is not working. The readme is an example for the upcoming 2.0 release, you're adding a 1.3.3 dependency.

Try adding bincode = "2.0.0-rc" as a dependency and the example should compile

c-git commented 4 months ago

Thanks that does fix it.