How to seal the const generic?

Hi team.
I am a contributor from the apache arrow-rs. We are trying to use the const generic to build the Decimal type, like this:

struct Decimal<const BYTE_LENGTH: usize> {...}

(here is the issue link: [Discussion] Refactor the `Decimal`s by using constant generic. · Issue #2001 · apache/arrow-rs · GitHub)
And we want to restrict the BYTE_LENGTH to be either 16 or 32.

However, as const_generic_exprs is an unstable feature, I can't add the value bound to the generic now, like this:

impl<const BYTE_LENGTH: usize> Decimal<BYTE_LENGTH>
where {BYTE_LENGTH == 16 || BYTE_LENGTH == 32}
{...}

Is there an alternative way to add bound to const generic? Or How could we sealed the const generic?

Would something like this work?

pub struct Decimal<const BYTE_LENGTH: usize> {
    digits: [u8; BYTE_LENGTH],
}

impl<const BYTE_LENGTH: usize> Decimal<BYTE_LENGTH> {
    pub const fn new(digits: [u8; BYTE_LENGTH]) -> Self
    where
        Decimal<BYTE_LENGTH>: sealed::ValidByteLength,
    {
        Decimal { digits }
    }
}

pub trait ValidByteLength {}

impl ValidByteLength for Decimal<16> {}
impl ValidByteLength for Decimal<32> {}

(playground)

You don't need to make this a "sealed" trait because downstream users aren't allowed to implement ValidByteLength for Decimal<N>.

2 Likes