Bare-metal array creation and return

Hi,

I’m new to Rust and trying to implement a bare metal application (with no_std) on ARM. Currently I want to read and write bytes from the SPI interface. The following snippet (kind of) works, but I would prefer to refactor it, so that I have different buffers for read and write. How can I create a object with a length (specified at creation time) without vec!?

pub fn transmit_bytes(buffer: &mut [u8]) {
    let trans_len = buffer.len();

    for b in buffer.iter() {
        send_byte(*b);
    }

    while transmit_fifo_full() {}

    for i in 0..trans_len {
        buffer[i] = recv_byte();
    }
}

Kind regards,
Roman

Your function already allows non-Vec objects of any lengths. For example, this allocates a buffer on the stack

let mut buf = [0u8; 100];
transmit_bytes(&mut buf);

But arrays have compile-time fixed size. For size variable at run time you need to allocate on the heap. For this an alternative to Vec is Box<[T]>, but it’s not worth the effort, since it’s effectively doing the same thing except tracking unused capacity, so the difference in overhead or performance is almost none.

Thank you. I guess I’m thinking the wrong way.

Why not get the user to pass in references to two arrays? That way one can be used for input and the other for output. The caller would then allocate a couple static arrays on the stack and pass them to your transmit_bytes() function as a slice.

That’s what I did now ;-).

What’s really important about this example is that transmit_bytes is accepting a slice (which, in the ABI, is equivalent to a pointer and a length). This means you can do this:

let mut buf = [0u8; 100];
transmit_bytes(&mut buf[50..100]);

Note that the 50, and the 100, can both be variables. So while the actual allocation is fixed size, the slice doesn’t have to be.

Thank you for pointing that out. Maybe that would be useful later.