Derive Macro Key

Source
#[derive(Key)]
{
    // Attributes available to this derive:
    #[key]
}
Expand description

Derive to implement the Key trait.

This derive implements the Key trait for a given type.

The Key trait is what allows fixed_map to set up storage for a type that will be the key in a fixed map.

Note: this requires the ::fixed_map crate to be in scope when it’s derived.


§Container attributes


Container attributes are attributes which apply directly onto container types. For Key this is just enums.


§#[key(bitset)]

This ensures that backing storage is performed with a bitset when used with a Set.

use fixed_map::{Key, Set};

#[derive(Clone, Copy, Key)]
pub enum Regular {
    First,
    Second,
    Third,
}

#[derive(Clone, Copy, Key)]
#[key(bitset)]
pub enum Bits {
    First,
    Second,
    Third,
}

// Normal storage uses an array of booleans:
assert_eq!(std::mem::size_of::<Set<Regular>>(), 3);

// Bitset storage uses a single u8 (or other appropriate type based on size):
assert_eq!(std::mem::size_of::<Set<Bits>>(), 1);

Note: not all operations will be implemented when this attribute is present, so some container methods might not work.


§Guide

Given the following enum:

use fixed_map::Key;

#[derive(Clone, Copy, Key)]
pub enum MyKey {
    First,
    Second,
    Third,
}

It performs the following expansion:

use fixed_map::Key;

#[derive(Clone, Copy)]
pub enum MyKey {
    First,
    Second,
    Third,
}

/// Build a storage struct containing an item for each key:
pub struct MyKeyMapStorage<V> {
    /// Storage for `MyKey::First`.
    f1: Option<V>,
    /// Storage for `MyKey::Second`.
    f2: Option<V>,
    /// Storage for `MyKey::Third`.
    f3: Option<V>,
}

/// Build a storage struct containing an element for each key:
pub struct MyKeySetStorage {
    data: [bool; 3],
}

/// Implement map storage for key.
impl<V> ::fixed_map::map::MapStorage<MyKey, V> for MyKeyMapStorage<V> {
    fn get(&self, key: MyKey) -> Option<&V> {
        match key {
            MyKey::First => self.f1.as_ref(),
            MyKey::Second => self.f2.as_ref(),
            MyKey::Third => self.f3.as_ref(),
        }
    }

    /* skipped */
}

/// Implement set storage for key.
impl ::fixed_map::set::SetStorage<MyKey> for MyKeySetStorage {
    fn contains(&self, key: MyKey) -> bool {
        let [a, b, c] = &self.data;

        match key {
            MyKey::First => *a,
            MyKey::Second => *b,
            MyKey::Third => *c,
        }
    }

    /* skipped */
}

impl<V> Default for MyKeyMapStorage<V> {
    fn default() -> Self {
        Self {
            f1: None,
            f2: None,
            f3: None,
        }
    }
}

impl Default for MyKeySetStorage {
    fn default() -> Self {
        Self {
            data: [false, false, false]
        }
    }
}

/// Implement the Key trait to point out storage.
impl ::fixed_map::Key for MyKey {
    type MapStorage<V> = MyKeyMapStorage<V>;
    type SetStorage = MyKeySetStorage;
}

See https://docs.rs/fixed-map.