I'm in the process of porting a low latency real-time application to Rust. Essentially I want to do as much as possible of the operations without copying. A major source of memory allocations right now are coming from the network stack. Every time a packet is received or send a lot of copying goes on under the hood to force and retrieve the bytes from a Rust structs. I want to stop doing this.
Essentially I want to be able to just convert the packets from/to bytes and transmit it. Below is a non-working example code that illustrates what I would like to do.
#[repr(C, align(4))]
#[derive(Debug)]
struct Content {
first: u8,
padding: [u8; 3]
}
#[repr(C, align(4))]
#[derive(Debug)]
struct Packet {
header_id: u16,
header_padding: [u8; 2],
// This is another pointer I want it to be located after header_padding
content: Box<[Content]>,
}
#[derive(Debug)]
struct ParsedPacket {
content_length: usize,
// The box below should directly reference the original u8 bytes without copying
packet: Box<Packet>,
}
unsafe fn buf_to_packet(bs: Box<[u8]>) -> Option<Box<ParsedPacket>> {
// How to implement this
// First 4 bytes are the header
// The rest must be 4 byte multiple and each 4 byte is a Content struct
// So from the length of the boxed slice we can infer the content_length
todo!()
}
unsafe fn packet_to_buf(bs: ParsedPacket) -> Box<[u8]> {
todo!()
}
fn main() {
let bytes = vec![
// Header
0, 23, 0, 0,
// Content 0
0, 0, 0, 0,
// Content 1
1, 0, 0, 0,
// Content 2
0, 0, 0, 0
].into_boxed_slice();
let packet = unsafe { buf_to_packet(bytes) };
println!("{:?}", content);
}
There are two problems with this. Rust requires the content to be a boxed slice. Which mains it necessarily isn't located in the struct itself but might be somewhere else. Also a boxed slice contains it's own bookkeeping about the length. I guess I need to do my own bookkeeping with the length. But I don't know how I can add a struct member with dynamic length without using a boxed slice.
I am of course willing to use unsafe to do it. But I'm not experienced with Rust so I don't know how I can actually implement this.
Essentially what I'm looking for in Rust is Flexible array members from C.