1 stable release

1.0.0 Nov 22, 2023

#629 in Procedural macros

Apache-2.0

16KB
236 lines

A macro for deriving Index & IndexMut implementations.

MASTER CI status crates.io badge docs.rs badge dependencies badge

Basic usage

// Derive only Index
index!(Struct by Enum => Output:
  Variant1 => field1,
  Variant2 => field2,
);

// Derive Index and IndexMut
index!(Struct by Enum => mut Output:
  Variant1 => field1,
  Variant2 => field2,
);

// Match/get by pattern
index!(Struct by Enum => Output:
  pat Enum::Variant(Foo::Bar) => field1,
  pat Enum::Index(idx) => pat field2[idx],
);

Example

use impl_index::index;

#[derive(Default)]
struct Struct {
    a: u8,
    arr: [u8; 10],
    thing_1: u8,
    thing_2: u8,
}

enum Enum {
    A,
    Arr(usize),
    Thing(Thing),
}

enum Thing {
    One,
    Two,
}

index!(Struct by Enum => mut u8:
    A => a,
    pat Enum::Arr(idx) if idx < 10 => pat arr[idx],
    pat Enum::Thing(Thing::One) => thing_1,
    pat _ => thing_2,
);

let mut s = Struct::default();

s[Enum::A] = 1;

for idx in 0u8..10 {
    s[Enum::Arr(idx.into())] = idx * 10;
}

s[Enum::Thing(Thing::One)] = 200;
s[Enum::Thing(Thing::Two)] = 201;

assert_eq!(s[Enum::A], 1, "A");
for idx in 0u8..10 {
    assert_eq!(s[Enum::Arr(idx.into())], idx * 10, "Arr({})", idx);
}
assert_eq!(s[Enum::Thing(Thing::One)], 200, "Thing(One)");
assert_eq!(s[Enum::Thing(Thing::Two)], 201, "Thing(Two)");

Generated output

#[automatically_derived]
impl ::core::ops::Index<Enum> for Struct {
    type Output = u8;
    fn index(&self, index_macro_derived_index_input: Enum) -> &Self::Output {
        match index_macro_derived_index_input {
            Enum::A => &self.a,
            Enum::Arr(idx) if idx < 10 => &self.arr[idx],
            Enum::Thing(Thing::One) => &self.thing_1,
            _ => &self.thing_2,
        }
    }
}
#[automatically_derived]
impl ::core::ops::IndexMut<Enum> for Struct {
    fn index_mut(&mut self, index_macro_derived_index_input: Enum) -> &mut Self::Output {
        match index_macro_derived_index_input {
            Enum::A => &mut self.a,
            Enum::Arr(idx) if idx < 10 => &mut self.arr[idx],
            Enum::Thing(Thing::One) => &mut self.thing_1,
            _ => &mut self.thing_2,
        }
    }
}

Example without generating IndexMut

This will fail to compile on instance[Idx::Foo] = 1;

struct Struct {
  foo: usize,
}

enum Idx {
  Foo,
}

index!(Struct by Idx => usize: Foo => foo);

let mut instance = Struct { foo: 0 };
instance[Idx::Foo] = 1;

Dependencies

~325–780KB
~19K SLoC