How to set a Rust array length dynamically?

ArraysRust

Arrays Problem Overview


I want to create array like this:

let arr = [0; length];

Where length is a usize. But I get this error

E0307
The length of an array is part of its type. For this reason, this length 
must be a compile-time constant.

Is it possible to create array with dynamic length? I want an array, not a Vec.

Arrays Solutions


Solution 1 - Arrays

> Is it possible to create array with dynamic length?

No. By definition, arrays have a length defined at compile time. A variable (because it can vary) is not known at compile time. The compiler would not know how much space to allocate on the stack to provide storage for the array.

You will need to use a Vec:

let arr = vec![0; length];

See also:

Solution 2 - Arrays

This should be possible after variable length arrays (VLA) are implemented.

Solution 3 - Arrays

You can create your own HeapArray. It's not that complicated if you read alloc's docs:

use std::alloc::{alloc, dealloc, Layout};
pub struct HeapArray<T> {
    ptr: *mut T,
    len: usize,
}

impl<T> HeapArray<T> {
    pub fn new(len: usize) -> Self {
        let ptr = unsafe {
            let layout = Layout::from_size_align_unchecked(len, std::mem::size_of::<T>());
            alloc(layout) as *mut T
        };
        Self { ptr, len }
    }
    pub fn get(&self, idx: usize) -> Option<&T> {
        if idx < self.len {
            unsafe { Some(&*(self.ptr.add(idx))) }
        } else {
            None
        }
    }
    pub fn get_mut(&self, idx: usize) -> Option<&mut T> {
        if idx < self.len {
            unsafe { Some(&mut *(self.ptr.add(idx))) }
        } else {
            None
        }
    }
    pub fn len(&self) -> usize {
        self.len
    }
}


impl<T> Drop for HeapArray<T> {
    fn drop(&mut self) {
        unsafe {
            dealloc(
                self.ptr as *mut u8,
                Layout::from_size_align_unchecked(self.len, std::mem::size_of::<T>()),
            )
        };
    }
}

impl<T> std::ops::Index<usize> for HeapArray<T> {
    type Output = T;
    fn index(&self, index: usize) -> &Self::Output {
        self.get(index).unwrap()
    }
}
impl<T> std::ops::IndexMut<usize> for HeapArray<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        self.get_mut(index).unwrap()
    }
}

You may also add methods like as_slice, get_unchecked, etc.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDima KudoshView Question on Stackoverflow
Solution 1 - ArraysShepmasterView Answer on Stackoverflow
Solution 2 - ArraysAaron ZorelView Answer on Stackoverflow
Solution 3 - ArraysTianyi ShiView Answer on Stackoverflow