tokio-rs / prost

PROST! a Protocol Buffers implementation for the Rust Language
Apache License 2.0
3.86k stars 501 forks source link

Question about expected behavior of `encode_varint` and `decode_varint`. #874

Open YoshikiTakashima opened 1 year ago

YoshikiTakashima commented 1 year ago

Running with 6375c4d0ea1ee133f6ca32fa21ac60db5e1168fa, the below test fails when pasted into src/encoding.rs. The decode seems to be returning 0.

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn decode_encode_roundtrip() {
        let mut buf: Vec<u8> = vec![0; 20];

        let value: u64 = 16384u64;
        encode_varint(value, &mut buf);
        let decoded_value = decode_varint(&mut buf.as_ref()).unwrap();

        assert_eq!(value, decoded_value);
    }
}
running 1 test
test encoding::test::decode_encode_roundtrip ... FAILED

failures:

---- encoding::test::decode_encode_roundtrip stdout ----
thread 'encoding::test::decode_encode_roundtrip' panicked at 'assertion failed: `(left == right)`
  left: `16384`,
 right: `0`', src/encoding.rs:1824:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Is this expected?

mumbleskates commented 8 months ago

if you insert before let decoded_value = ... the following debug line: println!("{buf:02x?}");, you will see that encode_varint has appended the bytes of the varint value 16384 to a buffer with twenty nul bytes:

---- encoding::test::decode_encode_roundtrip stdout ----
[00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 80, 7f]

That's how Vec<u8>'s implementation of bytes::BufMut works. callingdecode_varint on the slice view of that vec sees a nul byte first, which is a complete varint value 0, and returns that.

so yes, that's expected