user3032481
user3032481

Reputation: 608

How to use GenericArray with a limited range of length that can be detected at compile time?

For example,

struct Foo<T, N: ArrayLength<T>> {
    data: GenericArray<T, N>
}

I want the length of the data array to be limited within a range like 100 to 1024 bytes. Then, if the Foo is used like let f: Foo<u8, generic_array::typenum::U8> = Foo {data: GenericArray::default()};, it will cause a compilation error.

Upvotes: 1

Views: 252

Answers (2)

nnnmmm
nnnmmm

Reputation: 8764

I played around a little with typenum, this works:

use generic_array::{ArrayLength, GenericArray};
use typenum::{IsGreaterOrEqual, IsLessOrEqual, Same, B1, U100, U1024, U99};

struct Foo<T, N>
where
    N: ArrayLength<T>,
    N: IsGreaterOrEqual<U100, Output = True>,
    N: IsLessOrEqual<U1024, Output = True>,
{
    data: GenericArray<T, N>,
}

fn main() {
    let f: Foo<u8, U100> = Foo {
        data: GenericArray::default(),
    };
    // Does not compile
    let f: Foo<u8, U99> = Foo {
        data: GenericArray::default(),
    };
}

The IsGreaterOrEqual<M> etc. traits, confusingly, are implemented even when N < M. You have to get their result by looking at the associated Output type. If it is B1 or its synonym True, then N is indeed greater than or equal to M.

You might try to write a trait bound like <N as IsGreaterOrEqual<U100>>::Output == B1, but that's not possible. You can constrain an associated type either like in the code example, or by using a helper trait in typenum, Same: <N as IsGreaterOrEqual<U100>>::Output: Same<B1>.

Upvotes: 1

felix91gr
felix91gr

Reputation: 103

I think that what you want is Const Generics.

This feature exists in Rust, but it's still a work-in-progress. You can use it in nightly, and as far as I understand, there are some use cases that do work as intended.

Basically this allows you to have a generic type like this:

struct Foo<T, const N: usize> {
    // Here you can use `N` as a `const`. For example, to define the size of a `std::array`
}

Here are links to have or follow for this feature:


All in all, I think it's a shame that you can't use it in stable just yet. But great things take time to be built.

Check if you can use it. There are some std types that do use it today (and in stable because they have been audited to be sound and stable already). For example, std::array uses it extensively since at least 1 year ago.

I hope this helps <3

Upvotes: 1

Related Questions