Search code examples
rustrust-tokio

Why is printing an array of bytes shown out of order?


I'm writing a method that receives an instance of bytes::Bytes representing a Type/Length/Value data structure where byte 0 is the type, the next 4 the length and the remaining the value. I implemented a unit test that is behaving a very unexpected way.

Given the method:

fn split_into_packets(packet: &Bytes) -> Vec<Bytes> {
    let mut packets: Vec<Bytes> = Vec::new();
    let mut begin: usize = 1;
    while begin < packet.len() {
        let slice = &packet[1..5];
        print!("0: {} ", slice[0]);
        print!("1: {} ", slice[1]);
        print!("2: {} ", slice[2]);
        println!("3: {}", slice[3]);
        let size = u32::from_be_bytes(pop(slice));
        println!("{}", size);
    }
    return packets;
}

And the test:

let mut bytes = BytesMut::with_capacity(330);
bytes.extend_from_slice(b"R\x52\x00\x00\x00\x08\x00");
let packets = split_into_packets(&bytes.freeze());

I see the following on my console:

0: 82 1: 0 2: 0 3: 0

I expected it to be:

0: 0 1: 0 2: 0 3: 82

What's going on? What am I missing?


Solution

  • fn split_into_packets(packet: &Bytes) -> Vec<Bytes> { // paket = "R\x52\x00\x00\x00\x08\x00"
        let mut packets: Vec<Bytes> = Vec::new();
        let mut begin: usize = 1;
        while begin < packet.len() {
            let slice = &packet[1..5]; // slice = "\x52\x00\x00\x00"
            print!("0: {} ", slice[0]); // "\x52\x00\x00\x00"
                                            ^^^^
                                            |  |
                                            +--+--- this is slice[0] = 0x52 = 82 (in decimal)
            print!("1: {} ", slice[1]); // "\x52\x00\x00\x00"                                 
                                                ^^^^
                                                |  |
                                                +--+--- this is slice[1] = 0x0 = 0 (in decimal)
            print!("2: {} ", slice[2]); // "\x52\x00\x00\x00"                                 
                                                    ^^^^
                                                    |  |
                                                    +--+--- this is slice[2] = 0x0 = 0 (in decimal)
            println!("3: {}", slice[3]); // "\x52\x00\x00\x00"                                 
                                                         ^^^^
                                                         |  |
                                                         +--+--- this is slice[3] = 0x0 = 0 (in decimal)
            let size = u32::from_be_bytes(pop(slice));
            println!("{}", size);
        }
        return packets;
    }
    

    I hope the above explains why you get 82, 0, 0, 0 when printing the bytes one after another.

    So, onto the next thing: How do we convert 4 bytes to an u32: To do that there are two possibilities that differ in how they interpret the bytes:

    • from_be_bytes: Converts bytes to u32 in big-endian: u32::from_be_bytes([0x12, 0x34, 0x56, 0x78])==0x12345678
    • from_le_bytes: Converts bytes to u32 in little-endian: u32::from_le_bytes([0x78, 0x56, 0x34, 0x12])==0x12345678

    For endianess, you can e.g. consult the respective wikipedia page.