Struct construe::Construe

source ·
pub struct Construe<T, const N: usize> { /* private fields */ }
Expand description

Alternative to Vec for const

Used to write const functions as though they have a dynamically sized buffer (i.e. a Vec). It requires calling the function twice: on the first run, which uses N = 0, the Construe just pretends to store the items it is given, and it only tracks how many there are. Then wherever this function is invoked can use Construe::needs_len to determine the size of the buffer (i.e. the correct N) that is needed and invoke the same function again, but with a “real” buffer instead.

Implementations§

source§

impl<T> Construe<T, 0>

source

pub const fn start() -> Self

Create a Construe instance without the buffer

This instance will behave (almost) exactly the same as the instance that has the buffer. Crucially, it is used exactly the same, allowing you to write const functions that collect items into it as though it were a variably-sized buffer. Then, you simply call those functions twice: the first run (N = 0, using this constructor) determines the amount of space you need for the second run (where you use Construe::new with N = Construe::needs_len from before), which actually stores the collected items. Obviously, this requires that the functions are deterministic (though it will just panic if not).

source

pub const fn needs_len(&self) -> usize

Amount of items supposed to be stored in the buffer

This is the same as Construe::len, but it exists as a separate method that’s only implemented for N = 0 so that the const N: usize generic parameter on functions returning this can be inferred as 0 for the first run.

source§

impl<T, const N: usize> Construe<T, N>

source

pub const fn new() -> Self

Create a Construe instance (with or without the buffer)

Like Construe::start but for any N, allowing you to write functions that create their own Construe. They’ll need a const N generic, which the call site will use to indicate whether this is the first or second run.

source

pub const fn len(&self) -> usize

Amount of items stored (or supposed to be stored) in the buffer

source

pub const fn is_empty(&self) -> bool

Whether there are no items (supposed to be) stored in the buffer

source

pub const fn push(self, item: T) -> (Self, Option<T>)

Add item to the buffer

Note that this takes self by-value: since &mut references aren’t yet stable in const contexts, we have to keep reassigning the output of the function to the variable.

On the first run, when the buffer isn’t available yet, this returns the item inside the Option. This is necessary because there’s no way to restrict T to not have a destructor (which can’t be used by const functions). By giving back the T in case we can’t store it, we avoid taking on the responsibility to drop it.

use construe::Construe;
// `mut` because we pass it by-value
let mut construe = Construe::start();
// `.0` to ignore (i.e. drop) the `Option<&str>`
construe = construe.push("something").0;
source

pub const unsafe fn steal_from_slice(self, slice: &[T]) -> Self

Perform a bitwise copy of the slice contents into the buffer

This function is untested. If at all possible, loop over the slice and use Construe::push instead.

For Copy types, use copy_from instead.

Safety

Essentially, this function takes ownership of the contents of the slice. For several reasons, it is not currently possible to accept (and use) a [T; M] array by value. Because of this, the caller must pass in a slice of an array it owns, and then drop/forget the array immediately after this function returns.

This function may not be called outside of const contexts or with a T that needs to be dropped.

source

pub const fn finish(self) -> [T; N]

Return the filled buffer, consuming the struct

Panics if the buffer is not filled or if this is a zero-length buffer that was supposed to store items.

source§

impl<T: Copy, const N: usize> Construe<T, N>

source

pub const fn copy_from(self, slice: &[T]) -> Self

Copy all items from slice into the buffer

If the buffer has length zero, the offset is incremented all the same, the contents of the slice are just not stored.

Auto Trait Implementations§

§

impl<T, const N: usize> RefUnwindSafe for Construe<T, N>where T: RefUnwindSafe,

§

impl<T, const N: usize> Send for Construe<T, N>where T: Send,

§

impl<T, const N: usize> Sync for Construe<T, N>where T: Sync,

§

impl<T, const N: usize> Unpin for Construe<T, N>where T: Unpin,

§

impl<T, const N: usize> UnwindSafe for Construe<T, N>where T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.