I'm trying to create some bindings from a C library for rust with bindgen and everything was going well until I realized that my program was having memory leak problems
Thanks to heaptrack I was able to identify the function that was causing these memory leaks,
this function CP56Time2a_createFromMsTimestamp creates a timestamp to then be added to another structure (InformationObject) before being sent, when this structure is sent a method is called that frees the memory of the structure (InformationObject_destroy) and I guess also the memory of the timestamp, in the library there is no method to free the memory of the timestamp
How can I deallocate or free this memory? The resulting structure of the function is a pointer *mut sCP56Time2a
minimal example of what I'm doing:
use iec60870::bindings;
use std::ffi::CString;
pub struct CP56Time2a;
impl CP56Time2a {
pub fn create() -> *mut bindings::sCP56Time2a {
unsafe {
bindings::CP56Time2a_createFromMsTimestamp(
std::ptr::null_mut(),
bindings::Hal_getTimeInMs(),
)
}
}
}
pub struct Slave {
inner: bindings::CS104_Slave,
}
impl Slave {
pub fn new(addr: &str, port: i32) -> Self {
let inner = unsafe {
let inner = bindings::CS104_Slave_create(100, 100);
let address = CString::new(addr).unwrap().as_c_str().to_owned();
bindings::CS104_Slave_setLocalAddress(inner, address.as_ptr());
bindings::CS104_Slave_setLocalPort(inner, port);
bindings::CS104_Slave_setServerMode(inner, 1);
inner
};
Self { inner }
}
}
fn main() {
unsafe {
let slave = Slave::new("127.0.0.1", 2404);
let param = bindings::CS104_Slave_getAppLayerParameters(slave.inner);
let asdu = bindings::CS101_ASDU_create(param, false, 3, 0, 1, false, false);
let timestamp = CP56Time2a::create();
let me = bindings::MeasuredValueScaledWithCP56Time2a_create(
std::ptr::null_mut(),
1000,
20,
0,
timestamp,
);
bindings::CS101_ASDU_addInformationObject(asdu, me as bindings::InformationObject);
// send asdu
bindings::InformationObject_destroy(me as bindings::InformationObject);
bindings::CS101_ASDU_destroy(asdu);
}
}
Related
I am working on a project that involves reading different information from a file at different offsets.
Currently, I am using the following code:
// ------------------------ SECTORS PER CLUSTER ------------------------
// starts at 13
opened_file.seek(SeekFrom::Start(13)).unwrap();
let aux: &mut [u8] = &mut [0; 1];
let _buf = opened_file.read_exact(aux);
// ------------------------ RESERVED SECTORS ------------------------
// starts at 14
opened_file.seek(SeekFrom::Start(14)).unwrap();
let aux: &mut [u8] = &mut [0; 2];
let _buf = opened_file.read_exact(aux);
But as you can see, I need to create a new buffer of the size I want to read every time. I can't specify it directly as a parameter of the function.
I created a struct but I could not make a struct of all the different pieces of data I wanted. For example:
struct FileStruct {
a1: &mut [u8] &mut [0; 1],
a2: &mut [u8] &mut [0; 2],
}
Which are the types that are required for the read_exact method to work?
Is there a more effective way to read information from different offsets of a file without having to repeatedly copy-paste these lines of code for every piece of information I want to read from the file? Some sort of function, Cursor, or Vector to easily move around the offset? And a way to write this info into struct fields?
The easiest way is to have a struct of owned arrays, then seek and read into the struct.
use std::io::{self, prelude::*, SeekFrom};
#[derive(Debug, Clone, Default)]
struct FileStruct {
a1: [u8; 1],
a2: [u8; 2],
}
fn main() -> io::Result<()> {
let mut file_struct: FileStruct = Default::default();
let mut opened_file = unimplemented!(); // open file somehow
opened_file.seek(SeekFrom::Start(13))?;
opened_file.read_exact(&mut file_struct.a1)?;
opened_file.seek(SeekFrom::Start(14))?;
opened_file.read_exact(&mut file_struct.a2)?;
println!("{:?}", file_struct);
Ok(())
}
Playground link
This is still decently repetitive, so you can make a seek_read function to reduce the repetition:
use std::io::{self, prelude::*, SeekFrom};
#[derive(Debug, Clone, Default)]
struct FileStruct {
a1: [u8; 1],
a2: [u8; 2],
}
fn seek_read(mut reader: impl Read + Seek, offset: u64, buf: &mut [u8]) -> io::Result<()> {
reader.seek(SeekFrom::Start(offset))?;
reader.read_exact(buf)?;
Ok(())
}
fn main() -> io::Result<()> {
let mut file_struct: FileStruct = Default::default();
let mut opened_file = unimplemented!(); // open file somehow
seek_read(&mut opened_file, 13, &mut file_struct.a1)?;
seek_read(&mut opened_file, 14, &mut file_struct.a2)?;
println!("{:?}", file_struct);
Ok(())
}
Playground link
The repetition can be lowered even more by using a macro:
use std::io::{self, prelude::*, SeekFrom};
#[derive(Debug, Clone, Default)]
struct FileStruct {
a1: [u8; 1],
a2: [u8; 2],
}
macro_rules! read_offsets {
($file: ident, $file_struct: ident, []) => {};
($file: ident, $file_struct: ident, [$offset: expr => $field: ident $(, $offsets: expr => $fields: ident)*]) => {
$file.seek(SeekFrom::Start($offset))?;
$file.read_exact(&mut $file_struct.$field)?;
read_offsets!($file, $file_struct, [$($offsets => $fields),*]);
}
}
fn main() -> io::Result<()> {
let mut file_struct: FileStruct = Default::default();
let mut opened_file = unimplemented!(); // open file somehow
read_offsets!(opened_file, file_struct, [13 => a1, 14 => a2]);
println!("{:?}", file_struct);
Ok(())
}
Playground link
This is a complementary answer to Aplet123's: it's not quite clear that you must store the bytes as is into a structure, so you can also allocate one buffer (as a fixed-size array) and reuse it with the correctly sized slice e.g.
let mut buf = [0u8;16];
opened_file.read_exact(&mut buf[..4])?; // will read 4 bytes
// do thing with the first 4 bytes
opened_file.read_exact(&mut buf[..8])?; // will read 8 bytes this time
// etc...
You could also use the byteorder crate, which lets you directly read numbers or sequences of numbers. It basically just does the unrelying "create stack buffer of the right size; read; decode" for you.
That's especially useful because it looks a lot like "SECTORS PER CLUSTER" should be a u8 and "RESERVED SECTORS" should be a u16. With byteorder you can straight read_16() or read_u8().
Also building on Aplet123's answer, the following function seek_read doesn't require to know how many bytes to read at compile time, since it uses a Vector instead of a byte slice:
// Starting at `offset`, reads the `amount_to_read` from `reader`.
// Returns the bytes as a vector.
fn seek_read(
reader: &mut (impl Read + Seek),
offset: u64,
amount_to_read: usize,
) -> Result<Vec<u8>> {
// A buffer filled with as many zeros as we'll read with read_exact
let mut buf = vec![0; amount_to_read];
reader.seek(SeekFrom::Start(offset))?;
reader.read_exact(&mut buf)?;
Ok(buf)
}
Here are some tests to demonstrate how seek_read behaves:
use std::io::Cursor;
#[test]
fn seek_read_works() {
let bytes = b"Hello world!";
let mut reader = Cursor::new(bytes);
assert_eq!(seek_read(&mut reader, 0, 2).unwrap(), b"He");
assert_eq!(seek_read(&mut reader, 1, 4).unwrap(), b"ello");
assert_eq!(seek_read(&mut reader, 6, 5).unwrap(), b"world");
assert_eq!(seek_read(&mut reader, 2, 0).unwrap(), b"");
}
#[test]
#[should_panic(expected = "failed to fill whole buffer")]
fn seek_read_beyond_buffer_fails() {
let mut reader = Cursor::new(b"Hello world!");
seek_read(&mut reader, 6, 99).unwrap();
}
#[test]
#[should_panic(expected = "failed to fill whole buffer")]
fn start_seek_reading_beyond_buffer_fails() {
let mut reader = Cursor::new(b"Hello world!");
seek_read(&mut reader, 99, 1).unwrap();
}
I'm writing a MQTT5 library. To send a packet, I need to know the size of the payload before writing the payload. My solution for determining the size has the following constraints order by importance:
be easy to maintain
should not create copies of the data
should be fairly performant (avoid double calculations)
To determine the size I can do any of the following solutions:
do the calculations by hand, which is fairly annoying
hold a copy of the data to send in memory, which I want to avoid
Build an std::iter::ExactSizeIterator for the payload which consists of std::iter::Chains itself, which leads to ugly typings fast, if you don't create wrapper types
I decided to go with version 3.
The example below shows my try on writing a MQTT String iterator. A MQTT String consists of two bytes which are the length of the string followed by the data as utf8.
use std::iter::*;
use std::slice::Iter;
pub struct MQTTString<'a> {
chain: Chain<Iter<'a, u8>, Iter<'a, u8>>,
}
impl<'a> MQTTString<'a> {
pub fn new(s: &'a str) -> Self {
let u16_len = s.len() as u16;
let len_bytes = u16_len.to_be_bytes();
let len_iter = len_bytes.iter(); // len_bytes is borrowed here
let s_bytes = s.as_bytes();
let s_iter = s_bytes.iter();
let chain = len_iter.chain(s_iter);
MQTTString { chain }
}
}
impl<'a> Iterator for MQTTString<'a> {
type Item = &'a u8;
fn next(&mut self) -> Option<&'a u8> {
self.chain.next()
}
}
impl<'a> ExactSizeIterator for MQTTString<'a> {}
pub struct MQTTStringPait<'a> {
chain: Chain<std::slice::Iter<'a, u8>, std::slice::Iter<'a, u8>>,
}
This implementation doesn't compile because I borrow len_bytes instead of moving it, so it'd get dropped before the Chain can consume it:
error[E0515]: cannot return value referencing local variable `len_bytes`
--> src/lib.rs:19:9
|
12 | let len_iter = len_bytes.iter(); // len_bytes is borrowed here
| --------- `len_bytes` is borrowed here
...
19 | MQTTString { chain }
| ^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
Is there a nice way to do this? Adding len_bytes to the MQTTString struct doesn't help. Is there a better fourth option of solving the problem?
The root problem is that iter borrows the array. In nightly Rust, you can use array::IntoIter, but it does require that you change your iterator to return u8 instead of &u8:
#![feature(array_value_iter)]
use std::array::IntoIter;
use std::iter::*;
use std::slice::Iter;
pub struct MQTTString<'a> {
chain: Chain<IntoIter<u8, 2_usize>, Copied<Iter<'a, u8>>>,
}
impl<'a> MQTTString<'a> {
pub fn new(s: &'a str) -> Self {
let u16_len = s.len() as u16;
let len_bytes = u16_len.to_be_bytes();
let len_iter = std::array::IntoIter::new(len_bytes);
let s_bytes = s.as_bytes();
let s_iter = s_bytes.iter().copied();
let chain = len_iter.chain(s_iter);
MQTTString { chain }
}
}
impl<'a> Iterator for MQTTString<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
self.chain.next()
}
}
impl<'a> ExactSizeIterator for MQTTString<'a> {}
You could do the same thing in stable Rust by using a Vec, but that'd be a bit of overkill. Instead, since you know the exact size of the array, you could get the values and chain more:
use std::iter::{self, *};
use std::slice;
pub struct MQTTString<'a> {
chain: Chain<Chain<Once<u8>, Once<u8>>, Copied<slice::Iter<'a, u8>>>,
}
impl<'a> MQTTString<'a> {
pub fn new(s: &'a str) -> Self {
let u16_len = s.len() as u16;
let [a, b] = u16_len.to_be_bytes();
let s_bytes = s.as_bytes();
let s_iter = s_bytes.iter().copied();
let chain = iter::once(a).chain(iter::once(b)).chain(s_iter);
MQTTString { chain }
}
}
impl<'a> Iterator for MQTTString<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
self.chain.next()
}
}
impl<'a> ExactSizeIterator for MQTTString<'a> {}
See also:
How to implement Iterator and IntoIterator for a simple struct?
An iterator of &u8 is not a good idea from the point of view of pure efficiency. On a 64-bit system, &u8 takes up 64 bits, as opposed to the 8 bits that the u8 itself would take. Additionally, dealing with this data on a byte-by-byte basis will likely impede common optimizations around copying memory around.
Instead, I'd recommend creating something that can write itself to something implementing Write. One possible implementation:
use std::{
convert::TryFrom,
io::{self, Write},
};
pub struct MQTTString<'a>(&'a str);
impl MQTTString<'_> {
pub fn write_to(&self, mut w: impl Write) -> io::Result<()> {
let len = u16::try_from(self.0.len()).expect("length exceeded 16-bit");
let len = len.to_be_bytes();
w.write_all(&len)?;
w.write_all(self.0.as_bytes())?;
Ok(())
}
}
See also:
How do I convert between numeric types safely and idiomatically?
Converting number primitives (i32, f64, etc) to byte representations
I'm trying to combine my Rust program with a library written in C in a more complex scenario.
The library provides this interface:
use std::os::raw::{c_char, c_void};
extern "C" {
pub fn register_function(
name: *const c_char, signature: *const c_char,
func_ptr: *mut c_void, attachment: *mut c_void,
);
}
The signature can be a string describing the arguments and return type of the function as 32 or 64 bit ints and floats (representations: b'i' = i32, b'I' = i64, b'f' = f32, b'F' = f64). The registered function gets called with an array of u64 (uint64_t) values which correspond to the arguments from the signature.
I would like to abstract this registration and callback process, so that I can switch to another library in the future which provides a similar but different interface. My idea was to to create a proxy function that is registered instead of the actual function. This would then also provide a custom context struct.
My own functions could look like this:
use std::boxed::Box;
use std::pin::Pin;
fn return_void(context: Pin<Box<MyAttachment>>) {
// ...
}
fn return_32(context: Pin<Box<MyAttachment>>, a: u32, b: u32) -> u32 {
context.important_stuff();
// ...
}
// floating point values would be nice, but are optional
fn return_64(a: i32, b: i64, c: f64) -> f64 {
// ...
}
MyAttachment is supposed to be the context and provide the proxy function that gets an arbitrary number of arguments as array:
use std::cmp;
use std::ffi::CString;
use std::slice;
#[derive(PartialEq)]
enum ReturnType {
VOID,
BITS32,
BITS64,
}
struct MyAttachment {
real_func_ptr: *mut c_void,
signature: String,
argc: u32,
pass_attachment: bool,
return_type: ReturnType,
}
impl MyAttachment {
pub fn important_stuff(&self) {
// ...
}
unsafe extern "C" fn function_proxy(attachment: *mut c_void, argv: *mut u64) {
// Given: attachment is the pointer to MyAttachment and argv is the array of arguments.
let this = attachment.cast::<Self>();
if this.is_null() || argv.is_null() {
// error handling
return;
}
let this = Pin::new_unchecked(Box::from_raw(this)); // restore
let args = slice::from_raw_parts_mut(
argv,
// There is at least one element in argv if the function is supposed to return a value,
// because we need to write our result there.
cmp::max(
match this.return_type {
ReturnType::VOID => 0,
ReturnType::BITS32 | ReturnType::BITS64 => 1,
},
this.argc as usize,
),
);
let func_ptr = this.real_func_ptr;
// I can get the argument types from the signature.
// TODO cast to correct pointer type. For example:
// case return_void: Fn(Pin<Box<MyAttachment>>)
// case return_32: Fn(Pin<Box<MyAttachment>>, u64, u64) -> u32
// case return_64: Fn(u64, u64, f64) -> f64
// TODO call it:
if this.return_type != ReturnType::VOID {
//args[0] = func_ptr(...args);
// or
//args[0] = func_ptr(this, ...args);
} else {
//func_ptr(...args);
}
Box::into_raw(Pin::into_inner_unchecked(this)); // delay dropping of this
}
}
fn main() {
// defining functions like:
let func1 = Box::pin(MyAttachment {
real_func_ptr: return_32 as *mut _,
signature: String::from("(ii)i"),
argc: 2, // inferred from signature
pass_attachment: true,
return_type: ReturnType::BITS32, // inferred from signature
});
let name = CString::new("return_32").unwrap();
let signature = CString::new(func1.signature.as_str()).unwrap();
// leak the raw pointer
let func1_ptr = Box::into_raw(unsafe { Pin::into_inner_unchecked(func1) });
let _func1 = unsafe { Pin::new_unchecked(Box::from_raw(func1_ptr)) }; // just for housekeeping
unsafe {
register_function(
name.as_ptr(),
signature.as_ptr(),
MyAttachment::function_proxy as *mut _,
func1_ptr as *mut _,
)
};
// ...
// somewhere here is my proxy called from C
// ...
// automatic cleanup of MyAttachment structs, because the Boxes are dropped
}
How do I fill these TODOs with code?
I have seen this in C code somewhere by using a generic function pointer and defining a fixed number of calls:
void (*func_ptr)();
if (argc == 0)
func_ptr();
else if (argc == 1)
func_ptr(argv[0]);
else if (argc == 2)
func_ptr(argv[0], argv[1]);
// ... and so on
But is there a solution to do this in Rust? (This only needs to work for x86_64/amd64)
Thanks in advance for reading all this and trying to help.
(I added the reflection tag, because this would be done via reflection if Rust had any)
==== edit
I have seen these related questions, but I don't think they apply here:
Call a raw address from Rust -> My type is not given at compile time
How do I pass each element of a slice as a separate argument to a variadic C function? -> My arguments are somewhat of fixed size and don't use a valist
I'm trying to implement a basic library in Rust that creates an object and returns its pointer to C. The pointer I get doesn't look like it is on the heap — when I print it I get 0x1:
use std::fmt;
pub struct SndbDB {}
impl SndbDB {
fn new() -> SndbDB {
SndbDB {}
}
}
impl fmt::Display for SndbDB {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(sndb_db)")
}
}
// Implement a destructor just so we can see when the object is destroyed.
impl Drop for SndbDB {
fn drop(&mut self) {
println!("[rust] dropping {}", self);
}
}
#[no_mangle]
pub extern "C" fn sndb_db_create() -> *mut SndbDB {
let _db = Box::into_raw(Box::new(SndbDB::new()));
println!("[rust] creating DB {:?}", _db);
_db
}
#[no_mangle]
pub unsafe extern "C" fn sndb_db_destroy(ptr: *mut SndbDB) {
println!("[rust] destroying DB {:?}", ptr);
Box::from_raw(ptr); // Rust drops this for us.
}
The C calling code is trivial too:
typedef struct sndb_db sndb_db;
sndb_db * sndb_db_create(void);
void sndb_db_destroy(sndb_db* db);
void test_baseapi__create_and_destroy_db(void)
{
sndb_db * db = sndb_db_create();
printf("[C] Got db=%p\n",db);
sndb_db_destroy(db);
printf("[C] db should be dead by now...\n");
}
And all the output except the pointer location are as I expect:
[rust] creating DB 0x1
[C] Got db=0x1
[rust] destroying DB 0x1
[rust] dropping (sndb_db)
[C] db should be dead by now...
I know that memory allocated in Rust needs to be deallocated by Rust - but I'm still surprised it is using a location of 0x1 - am I doing something wrong, is something odd happening, or is this all OK?
It looks like this is an optimisation by Rust since the SndbDB struct has no state.
Adding an i: u32 field to it and plumbing that through to the constructor functions and the C code I then get:
[rust] creating DB 0x7fff2fe00000
[C] Got db=0x7fff2fe00000
[rust] destroying DB 0x7fff2fe00000
[rust] dropping (sndb_db i=123)
[C] db should be dead by now...
However I'd still love to find an official source to back up this guess.
static variable A_INTERSECTS_A from the following code returns the error.
This piece of code should return a big 1356x1356 2D array of bool.
use lazy_static::lazy_static; // 1.2.0
#[derive(Debug, Copy, Clone, Default)]
pub struct A {
pub field_a: [B; 2],
pub ordinal: i32,
}
#[derive(Debug, Copy, Clone, Default)]
pub struct B {
pub ordinal: i32,
}
pub const A_COUNT: i32 = 1356;
lazy_static! {
pub static ref A_VALUES: [A; A_COUNT as usize] = { [A::default(); A_COUNT as usize] };
pub static ref A_INTERSECTS_A: [[bool; A_COUNT as usize]; A_COUNT as usize] = {
let mut result = [[false; A_COUNT as usize]; A_COUNT as usize];
for item_one in A_VALUES.iter() {
for item_two in A_VALUES.iter() {
if item_one.field_a[0].ordinal == item_two.field_a[0].ordinal
|| item_one.field_a[0].ordinal == item_two.field_a[1].ordinal
|| item_one.field_a[1].ordinal == item_two.field_a[0].ordinal
|| item_one.field_a[1].ordinal == item_two.field_a[1].ordinal
{
result[item_one.ordinal as usize][item_two.ordinal as usize] = true;
}
}
}
result
};
}
fn main() {
A_INTERSECTS_A[1][1];
}
I've seen people dealing with this by implementing Drop for structs in a large list, but there aren't any structs in my list and you cant implement it for bool.
If I change A_INTERSECTS_A: [[bool; A_COUNT as usize]; A_COUNT as usize] to A_INTERSECTS_A: Box<Vec<Vec<bool>>> the code works fine, but I really would like to use an array here.
The problem here is almost certainly the huge result array that is being placed on the stack when the initialisation code of A_INTERSECTS_A runs. It is 13562 ≈ 1.8 MB, which is of a similar order of magnitude to the size of the stack. In fact, it is larger than Windows' default size of 1 MB (and I suspect you are on Windows, given you've got that error message).
The solution here is to reduce the stack size by moving it to the heap, by, for instance, using Vec instead (as you indicate works), or using a Box. This will have the added benefit that the initialisation code doesn't have to do a 2MB copy from the stack to A_INTERSECTS_A's memory (it only needs to copy some pointers around).
A direct translation to using a Box:
pub static ref A_INTERSECTS_A: Box<[[bool; A_COUNT as usize]; A_COUNT as usize]> = {
let mut result = Box::new([[false; A_COUNT as usize]; A_COUNT as usize]);
// ...
}
unfortunately doesn't work: Box::new is a normal function call, and hence its argument is placed directly onto the stack.
However, if you're using a nightly compiler and are willing to use unstable features, you can use "placement box", which is literally designed for this purpose: it allocates space on the heap and constructs the value straight into that memory, avoiding intermediate copies, and avoiding the need to have the data on the stack. This simply requires replacing Box::new with box:
let mut result = box [[false; A_COUNT as usize]; A_COUNT as usize];
If you (very sensibly) prefer to stick to stable releases, an alternative until that stabilises is to just replace the outer layer of the arrays with a Vec: this retains all the data locality benefits of the arrays (everything is laid out contiguously in memory), although is slightly weaker in terms of static knowledge (the compiler can't be sure that the length is 1356). Since [_; A_COUNT] doesn't implement Clone, this cannot use thevec!` macro and hence (unfortunately) looks like:
pub static ref A_INTERSECTS_A: Vec<[bool; A_COUNT as usize]> = {
let mut result =
(0..A_COUNT as usize)
.map(|_| [false; A_COUNT as usize])
.collect::<Vec<_>>();
// ...
}
If you absolutely need all the arrays, one could do some unsafe magic to extract this down to the original Box<[[bool; ...]; ...]> from the Vec. It requires two steps (via into_boxed_slice), because a Box<T> needs to have an allocation sized perfectly for T, while a Vec may overallocate in order to achieve its O(1) amortization. This version would look like:
pub static ref A_INTERSECTS_A: Box<[[bool; A_COUNT as usize]; A_COUNT as usize]> = {
let mut result =
(0..A_COUNT as usize)
.map(|_| [false; A_COUNT as usize])
.collect::<Vec<_>>();
// ...
// ensure the allocation is correctly sized
let mut slice: Box<[[bool; A_COUNT as usize]]> = result.into_boxed_slice();
// pointer to the start of the slices in memory
let ptr: *mut [bool; A_COUNT as usize] = slice.as_mut_ptr();
// stop `slice`'s destructor deallocating the memory
mem::forget(slice);
// `ptr` is actually a pointer to exactly A_COUNT of the arrays!
let new_ptr = ptr as *mut [[bool; A_COUNT as usize]; A_COUNT as usize];
unsafe {
// let this `Box` manage that memory
Box::from_raw(new_ptr)
}
}
I've added in some explicit types so that what's going in is a little more clear. This works because Vec<T> exposes into_boxed_slice, and hence we can munge that Box<[T]> (i.e. dynamic length) into a Box<[T; len]> given we know the exact length at compile time.