konst

Macro const_eq_for

Source
macro_rules! const_eq_for {
    (
        slice;
        $left_slice:expr,
        $right_slice:expr
        $(, $($comparison:tt)* )?
    ) => { ... };
    (
        option;
        $left_opt:expr,
        $right_opt:expr
        $(, $($comparison:tt)* )?
    ) => { ... };
    (
        range;
        $left_range:expr,
        $right_range:expr
        $(, $($comparison:tt)* )?
    ) => { ... };
    (
        range_inclusive;
        $left_range:expr,
        $right_range:expr
        $(, $($comparison:tt)* )?
    ) => { ... };
}
Expand description

Compares two standard library types for equality, that can’t be compared with const_eq.

§Types

This macro supports multiple types with different prefixes:

  • slice: for comparing &[T]. example

  • option: for comparing Option<T>. example

  • range: for comparing Range<T>. example

  • range_inclusive: for comparing RangeInclusive<T>. example

§Limitations

The arguments must be concrete types, and have a fully inferred type. eg: if you pass an integer literal it must have a suffix to indicate its type.

§Arguments

The arguments take this form

const_eq_for!(type; left_value, right_value <comparator> )

§Comparator argument

The <comparator> argument can be any of:

  • (passing nothing): Compares the item using the const_eq macro. example

  • , |item| <expression>: Converts the item with <expression> to a type that can be compared using the const_eq macro. example

  • , |left_item, right_item| <expression>: Compares the items with <expression>, which must evaluate to a bool. example

  • , path::to::function: Compares the items using the passed function, which must evaluate to a bool. example

§Examples

§Comparing slices of structs

use konst::{const_eq_for, eq_str};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Location {
    pub file: &'static str,
    pub column: u32,
    pub line: u32,
}

konst::impl_cmp! {
    impl Location;
     
    pub const fn const_eq(&self, other: &Self) -> bool {
        eq_str(self.file, other.file) &&
        self.column == other.column &&
        self.line == other.line
    }
}

const HERE: &[Location] = &[here!(), here!(), here!(), here!()];

const THERE: &[Location] = &[here!(), here!(), here!(), here!()];

const _: () = {
    assert!( const_eq_for!(slice; HERE, HERE));
    assert!(!const_eq_for!(slice; HERE, THERE));
    assert!( const_eq_for!(slice; THERE, THERE));
};

§Comparing slices of field-less enums

#[derive(Copy, Clone)]
enum Direction {
    Left,
    Right,
    Up,
    Down,
}

use Direction::*;

const fn eq_slice_direction(left: &[Direction], right: &[Direction]) -> bool {
    konst::const_eq_for!(slice; left, right, |&x| x as u8)
}

const CHEAT_CODE: &[Direction] = &[Up, Up, Down, Down, Left, Right, Left, Right];

const CLOCKWISE: &[Direction] = &[Up, Right, Down, Left];

const _: () = {
    assert!( eq_slice_direction(CHEAT_CODE, CHEAT_CODE));
    assert!(!eq_slice_direction(CHEAT_CODE, CLOCKWISE));
    assert!( eq_slice_direction(CLOCKWISE, CLOCKWISE));
};

§Comparing Options

use konst::const_eq_for;

const SOME: Option<(u32, u32)> = Some((3, 5));
const NONE: Option<(u32, u32)> = None;

const fn eq_opt_tuple(left: &Option<(u32, u32)>, right: &Option<(u32, u32)>) -> bool {
    const_eq_for!(option; left, right, |l, r| l.0 == r.0 && l.1 == r.1 )
}

const _: () = {
    assert!( eq_opt_tuple(&SOME, &SOME));
    assert!(!eq_opt_tuple(&SOME, &NONE));
    assert!( eq_opt_tuple(&NONE, &NONE));
};

§Comparing Ranges

use konst::{const_eq_for, impl_cmp};

use std::ops::Range;

#[derive(Copy, Clone)]
pub enum Month {
    January,
    February,
    March,
    April,
    May,
    June,
    July,
    August,
    September,
    October,
    November,
    December,
}

use Month::*;

konst::impl_cmp! {
    impl Month;
     
    pub const fn const_eq(&self, other: &Self) -> bool {
        *self as u8 == *other as u8
    }
}

const FOO: Range<Month> = January..April;
const BAR: Range<Month> = October..December;

const _: () = {
    assert!( const_eq_for!(range; FOO, FOO));
    assert!(!const_eq_for!(range; FOO, BAR));
    assert!( const_eq_for!(range; BAR, BAR));
};

§Comparing RangeInclusives

use konst::{const_eq_for, impl_cmp};

use std::ops::RangeInclusive;

#[derive(Copy, Clone)]
pub enum WeekDay {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
}

use WeekDay::*;

konst::impl_cmp! {
    impl WeekDay;
     
    pub const fn const_eq(&self, other: &Self) -> bool {
        *self as u8 == *other as u8
    }
}

const FOO: RangeInclusive<WeekDay> = Monday..=Thursday;
const BAR: RangeInclusive<WeekDay> = Friday..=Sunday;

const _: () = {
    assert!( const_eq_for!(range_inclusive; FOO, FOO));
    assert!(!const_eq_for!(range_inclusive; FOO, BAR, WeekDay::const_eq));
    assert!( const_eq_for!(range_inclusive; BAR, BAR, WeekDay::const_eq));
};