Search code examples
rust

Implement BitOr trait for "group of types"


I have a

struct Val<U, const OFS: u8, const LEN: u8> {
value: U,

}

This "type group" can be any type OFS:0..255, LEN:0..255 for U, so 65536 different types per U.

I want to be able to BitOr any instance of this "type group" with each other.

Here my sample test case :

#![allow(non_camel_case_types)]
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(dead_code)]

use core::ops::BitOr;

/// a value, at offset with length
#[derive(Debug)]
struct Val<U, const OFS: u8, const LEN: u8> {
    value: U,
}

/// BitOr for u16
impl<const OFS: u8, const LEN: u8> BitOr for Val<u16, OFS, LEN> {
    type Output = u16;

    fn bitor(self, rhs: Self) -> Self::Output {
        self.value << OFS | rhs.value << OFS
    }
}

///
fn main() {
    type T_1 = Val<u16, 0, 1>;
    let v_1 = T_1 { value: 0b0001 };

    type T_2 = Val<u16, 1, 2>;
    let v_2 = T_2 { value: 0b0010 };

    let v = v_1 | v_2;
    
    assert_eq!(0b0011, v);

    println!("v_1 = {:?}", v_1);
    println!("v_2 = {:?}", v_2);
    println!("v = {:?}", v);
}

The compile error is error[E0308]: mismatched types at let v = v_1 | v_2;

I understand that T_1 and T_2 are different types.

So how can I do BitOr on these different types?


Solution

  • The BitOr trait has a Rhs type parameter (that defaults to Self if omitted). In this case, you want to supply the different instantiation of the Val type:

    impl<const OFSA: u8, const LENA: u8, const OFSB: u8, const LENB: u8> BitOr<Val<u16, OFSB, LENB>>
        for Val<u16, OFSA, LENA>
    {
        type Output = u16;
    
        fn bitor(self, rhs: Val<u16, OFSB, LENB>) -> Self::Output {
            self.value << OFSA | rhs.value << OFSB
        }
    }
    

    See it on the playground.