Help repurpose a simple macro for another job

Hi Guys,

Yesterday on the discord chatroom, a very badass rustaceon @Kixiron, gifted me this wonderful macro:

macro_rules! helper {
        (@inner [$($acc:tt)*] []) => {
            vec![$($acc)*]
        };
        (@inner [$($acc:tt)*] [$lit:literal $(, $($rest:tt)*)?]) => {
            helper!(@inner [$($acc)* Some($lit),] [$($($rest)*)?])
        };
        (@inner [$($acc:tt)*] [x $(, $($rest:tt)*)?]) => {
            helper!(@inner [$($acc)* None,] [$($($rest)*)?])
        };
        ($($rest:tt)*) => {
            helper!(@inner [] [$($rest)*])
        };
    }

    fn main() {
        let test = helper![
            x,1,5,x,x,2,6,0,x,3,7,1,
            x,4,8,2,x,x,9,3,0,6,10,
            x,1,7,11,5,2,8,12,6,3,9,
            13,7,4,x,14,8,5,11,x,x,
            6,12,x,10,7,13,x,11,8,
            14,x,12,9,x,x,13,
        ];
        
        println!("{:?}", test);
    }

Which takes helper![x,1,5]; and turns it into [None,Some(1),Some(5)];

I was wondering if anyone could convert it to now take:

let test = helper![[north,east], [south,west]]

and turn it into:

let test: [ArrayVec<[Side; 2]>; 2] = [[Side::North, Side::East].into(), [Side::South, Side::West].into()];

(making the size of the outer array adjust to fit, (or be 15 * 15) , whereas the inner will always be 2

UPDATE/

Warning: ArrayVec<[Side; 2]> = [Side::North].into() does not work!!... Would need to be:

let mut foo: ArrayVec<[Side; 2]> = ArrayVec::new();
foo.push(Side::North);

/UPDATE

ultimately, the final goal will be to have this:

let truth_table = array_of_arrayvecs![
        [],[east],[east],[east],[east],[south],[south,east],[south,east],[south,east],[south,east],[south],[south,east],[south,east],[south,east],[south,east],
        [west],[],[east],[east],[east],[south,west],[south],[south,east],[south,east],[south,east],[south,west],[south],[south,east],[south,east],[south,east],
        [west],[west],[],[east],[east],[south,west],[south,west],[south],[south,east],[south,east],[south,west],[south,west],[south],[south,east],[south,east],
        [west],[west],[west],[],[east],[south,west],[south,west],[south,west],[south],[south,east],[south,west],[south,west],[south,west],[south],[south,east],
        [west],[west],[west],[west],[],[south,west],[south,west],[south,west],[south,west],[south],[south,west],[south,west],[south,west],[south,west],[south],
        //...
];

Thanks so much! :smiley:

#![recursion_limit="500"]

use arrayvec::ArrayVec;

macro_rules! array_of_arrayvecs {
    (@inner {$($acc:tt)*} {[] $(, $($rest:tt)*)?}) => {
        array_of_arrayvecs!(@inner {$($acc)* arrayvec::ArrayVec::<[Side; 2]>::new().into(), } {$($($rest)*)?})
    };
    (@inner {$($acc:tt)*} {[$first:ident] $(, $($rest:tt)*)?}) => {
        {
            let mut temp_arrayvec = arrayvec::ArrayVec::<[Side; 2]>::new();
            temp_arrayvec.push(Side::$first);
            array_of_arrayvecs!(@inner {$($acc)* temp_arrayvec, } {$($($rest)*)?})
        }
    };
    (@inner {$($acc:tt)*} {[$first:ident ,$second:ident] $(, $($rest:tt)*)?}) => {
        array_of_arrayvecs!(@inner {$($acc)* [Side::$first ,Side::$second].into(), } {$($($rest)*)?})
    };
    (@inner {$($rest:tt)*} {}) => {
        [$($rest)*]
    };
    ($($rest:tt)*) => {
        array_of_arrayvecs!(@inner {} {$($rest)*})
    };
}

#[derive(Debug)]
pub enum Side {
    North,
    East,
    South,
    West,
}

fn main() {
    let test1: [ArrayVec<[Side; 2]>; 2] = array_of_arrayvecs![[North, East], [South, West]];
    let expected1: [ArrayVec<[Side; 2]>; 2] = [
        [Side::North, Side::East].into(),
        [Side::South, Side::West].into(),
    ];

    let test2: [ArrayVec<[Side; 2]>; 10] = array_of_arrayvecs![
        [],
        [East],
        [East],
        [East],
        [East],
        [South],
        [South, East],
        [South, East],
        [South, East],
        [South, East]
    ];
    
    let truth_table = array_of_arrayvecs![
        [],[East],[East],[East],[East],[South],[South,East],[South,East],[South,East],[South,East],[South],[South,East],[South,East],[South,East],[South,East],
        [West],[],[East],[East],[East],[South,West],[South],[South,East],[South,East],[South,East],[South,West],[South],[South,East],[South,East],[South,East],
        [West],[West],[],[East],[East],[South,West],[South,West],[South],[South,East],[South,East],[South,West],[South,West],[South],[South,East],[South,East],
        [West],[West],[West],[],[East],[South,West],[South,West],[South,West],[South],[South,East],[South,West],[South,West],[South,West],[South],[South,East],
        [West],[West],[West],[West],[],[South,West],[South,West],[South,West],[South,West],[South],[South,West],[South,West],[South,West],[South,West],[South],
    
        [North],[North,East],[North,East],[North,East],[North,East],[],[East],[East],[East],[East],[South],[South,East],[South,East],[South,East],[South,East],
        [North,West],[North],[North,East],[North,East],[North,East],[West],[],[East],[East],[East],[South,West],[South],[South,East],[South,East],[South,East],
        [North,West],[North,West],[North],[North,East],[North,East],[West],[West],[],[East],[East],[South,West],[South,West],[South],[South,East],[South,East],
        [North,West],[North,West],[North,West],[North],[North,East],[West],[West],[West],[],[East],[South,West],[South,West],[South,West],[South],[South,East],
        [North,West],[North,West],[North,West],[North,West],[North],[West],[West],[West],[West],[],[South,West],[South,West],[South,West],[South,West],[South],

        [North],[North,East],[North,East],[North,East],[North,East],[North],[North,East],[North,East],[North,East],[North,East],[],[East],[East],[East],[East],
        [North,West],[North],[North,East],[North,East],[North,East],[North,West],[North],[North,East],[North,East],[North,East],[West],[],[East],[East],[East],
        [North,West],[North,West],[North],[North,East],[North,East],[North,West],[North,West],[North],[North,East],[North,East],[West],[West],[],[East],[East],
        [North,West],[North,West],[North,West],[North],[North,East],[North,West],[North,West],[North,West],[North],[North,East],[West],[West],[West],[],[East],
        [North,West],[North,West],[North,West],[North,West],[North],[North,West],[North,West],[North,West],[North,West],[North],[West],[West],[West],[West],[],
    ];

    println!("Test1: {:?}, Expected1: {:?}", test1, expected1);
    println!("Test2: {:?}", test2);
    println!("truth_table: {:?}", truth_table);
}

Thanks very much for your help!

1 Like