Nur
Nur

Reputation: 2473

Const expressions inside trait?

I have a trait that look like this:

pub trait Buf<const N: usize> {
    fn to_buf(&self) -> [u8; N];
    fn from_buf(buf: [u8; N]) -> Self;
}

However I want to do something like this:

trait Buf {
    const N: usize;
    fn to_buf(&self) -> [u8; Self::N];
    fn from_buf(buf: [u8; Self::N]) -> Self;
}

It give me this error (playground):

   |
   |     fn to_buf(&self) -> [u8; Self::N];
   |                              ^^^^^^^ cannot perform const operation using `Self`
   |
   = note: type parameters may not be used in const expressions
   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions

Is it possible?

Upvotes: 3

Views: 2256

Answers (2)

Nur
Nur

Reputation: 2473

After some research, I found out that, In nightly, Rust allow us to use generic const expression, under this (#![feature(generic_const_exprs)]) feature flag,

However, This is still far from being stable.

#![allow(warnings)]
#![feature(generic_const_exprs)]

trait Buf {
    const N: usize;
    fn to_buf(&self) -> [u8; Self::N];
    fn from_buf(buf: [u8; Self::N]) -> Self;
}
macro_rules! impl_trait {
    ($name:ident for $($t:ty:$N:literal)*) => ($(
        impl $name for $t {
            const N: usize = $N;
            fn to_buf(&self) -> [u8; $N] {
                self.to_le_bytes()
            }
            fn from_buf(bytes: [u8; $N]) -> Self {
                Self::from_le_bytes(bytes)
            }
        }
    )*)
}
impl_trait!(Buf for u8:1 u16:2 u32:4 i8:1 i16:2 i32:4);

fn test<T: Buf>(buf: T, rhs: [u8; T::N])
where
    [u8; T::N]:,
{
    assert_eq!(buf.to_buf(), rhs);
}

fn main() {
    test(123_u8,  [123]);
    test(123_u16, [123, 0]);
    test(123_u32, [123, 0, 0, 0]);

    test(-123i8,  [133]);
    test(-123i16, [133, 255]);
    test(-123i32, [133, 255, 255, 255]);
}

Rust Playground

Upvotes: 1

user1486999
user1486999

Reputation: 61

You can either use the <T: Buf<8>> signature, like

fn a<T: Buf<8>>(buf: T) {
    println!("{:#?}", buf.to_buf());
}

or run

#![feature(trait_alias)] 
trait Buf8 = Buf<8>;

fn a<T: Buf8>(buf: T) {
    println!("{:#?}", buf.to_buf());
}

in experimental rust.

Upvotes: 0

Related Questions