Crate loaf

source · []
Expand description

Why have a slice when you can have a loaf?

What this is

Sometimes you know that a slice must have at least one element in it, but Rust forces you to do “last minute decision” by unwrap()ing Option from for example first() for split_first() methods.

Loaf guarantees to have at least one element by its definition.

How it works

First, lets consider a simple slice

let x: &[u8] = &[10, 42, 0, 7, 91];

&[u8] underneath is really just a pair of a pointer to buffer and its length (a fat pointer)

[ ptr: *const u8 | len: usize = 5 ]
   |                |
   |                v       
   |    | <-       [u8]       -> |
   |    +----+----+----+----+----+
   +--->| 10 | 42 | 00 | 07 | 91 |
        +----+----+----+----+----+

Thats because size of [u8] can be known only at runtime.

Rust also allows to define a structure that has exactly one dynamically-sized type at the end of it.

struct LoafT<u8, 2> {
    loaf: [u8; 2],
    rest: [u8],
}
let x: &[u8] = &[10, 42, 0, 7, 91];
let loaf: &LoafN<u8, 2> = abracadabra!(slice);

In this case the len also contains the length of [u8]

[ ptr: *const ?? | len: usize = 3 ]
   |                     |
   |                     v       
   |    | [u8; 2] | <-  [u8]  -> |
   |    +----+----+----+----+----+
   +--->| 10 | 42 | 00 | 07 | 91 |
        +----+----+----+----+----+

ptr doesn’t have here a clear type, because *const LoafN<u8, 2> is itself a fat pointer (because of the [u8] field).

The Hack

Rust does have a way to fiddle with fat pointer internals, but it requires ptr_metadata feature, which are only avaliable on nightly. The hack here is to create an *mut [T] as it was *mut Loaf<T> and then cast it.

See Loaf::from_slice source code for more details

Safety

As long as two arrays could be interpreted as one bigger and vice versa, everything should be alright

Structs

Slice that guarantees to have at least one element