Just thought I'd share a macro I made recently that others here might appreciate. If you have ideas for improvements, I'll all ears. I do want to modify it so that it can accept variable number of columns.
This macro generates a rustdoc markdown table from data. It also generates constants to index into an array.
md_data_table! {
MyOffsets
| DATA_TAG | 2 |
| DATA_TAG_EXT | 2 |
| LENGTH | 4 |
| CODE | 12 |
}
#[macro_export]
macro_rules! md_data_table {
( $Table:ident $(| $ident:ident | $length:literal |)* ) => {
md_table!($Table $(| $ident | $length |)*);
impl $Table {
data_table!($(| $ident | $length |)*);
}
};
}
#[macro_export]
macro_rules! md_table {
( $Table:ident $(| $ident:ident | $length:literal |)* ) => {
///
#[doc = "| Name | Len |"]
#[doc = "| -- | -- |"]
$(
#[doc = concat!("| ", stringify!($ident), " | ", stringify!($length), " |")]
)*
#[allow(unused)]
struct $Table;
};
}
#[macro_export]
macro_rules! data_table {
( $(| $ident:ident | $length:literal |)* ) => {
data_table!(0 => $(| $ident | $length |)* );
};
($offset:expr => | $a_ident:ident | $a_length:literal |) => {
#[allow(unused)]
const $a_ident: std::ops::Range<usize> = (($offset)..(($offset) + $a_length));
};
($offset:expr => | $a_ident:ident | $a_length:literal | $(| $ident:ident | $length:literal |)* ) => {
#[allow(unused)]
const $a_ident: std::ops::Range<usize> = (($offset)..(($offset) + $a_length));
data_table!($offset + $a_length => $(| $ident | $length |)* );
};
}
Expanded this generates something like:
///
#[doc = "| Name | Len |"]
#[doc = "| -- | -- |"]
#[doc = "| DATA_TAG | 2 |"]
#[doc = "| DATA_TAG_EXT | 2 |"]
#[doc = "| LENGTH | 4 |"]
#[doc = "| CODE | 12 |"]
#[allow(unused)]
struct MyOffsets;
impl MyOffsets {
#[allow(unused)]
const DATA_TAG: std::ops::Range<usize> = ((0)..((0) + 2));
#[allow(unused)]
const DATA_TAG_EXT: std::ops::Range<usize> = ((0 + 2)..((0 + 2) + 2));
#[allow(unused)]
const LENGTH: std::ops::Range<usize> = ((0 + 2 + 2)..((0 + 2 + 2) + 4));
#[allow(unused)]
const CODE: std::ops::Range<usize> =
((0 + 2 + 2 + 4)..((0 + 2 + 2 + 4) + 12));
}