Struct with specific byte size and layout

Hi,

I'm attempting to follow along with this series discussing how to build a simple sqlite clone and I'm attempting to write it in Rust.

I'm having trouble understanding how to achieve the serialization that is done in C, in Rust

So (in C) there is a struct to represent a Row

#define COLUMN_USERNAME_SIZE 32
#define COLUMN_EMAIL_SIZE 255
typedef struct {
  uint32_t id;
  char username[COLUMN_USERNAME_SIZE];
  char email[COLUMN_EMAIL_SIZE];
} Row;

And the layout of the struct once serialized is very exact -

Attempting to recreate that same struct in rust however gives very different results

Rust Playground

The size of the struct ends up being 1152 bytes instead of the expected 291, what is the reason for the difference and how could I achieve the layout that I need here?

use std::mem::size_of;


#[repr(C, packed)]
struct Row{
    id: u32,
    username: [char; 32],
    email: [char; 255]
}

fn main() {
    println!("Row occupies {} bytes.", size_of::<Row>());
}

Output -

Row occupies 1152 bytes.

The reason for the difference is that Rust's char and C's char are not the same at all: in Rust char is a Unicode scalar value and is 4 bytes, while in C it is just one byte. You need u8.

However, note that in Rust structs layout is not guaranteed: you need to add #[repr(C)] to make it "like C". I see you already have it, sorry. Although packed is not the default in C.

Also, I would recommend to not rely on structs for serializations but rather use proper serialization/deserialization (probably with serde) because padding can sneak and serialization is hard in general.

2 Likes