quick arrays
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock46
-rw-r--r--Cargo.toml15
-rw-r--r--src/lib.rs89
4 files changed, 151 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..8afdb15
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,46 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "amap"
+version = "0.1.0"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..e1ce0d6
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "amap"
+version = "0.1.0"
+author = ["bend-n <[email protected]>"]
+description = "define `[Option<T>; N]` easily"
+edition = "2021"
+repository = "https://github.com/bend-n/amap.git"
+license = "MIT"
+
+[dependencies]
+quote = "1.0.32"
+syn = "2.0.15"
+
+[lib]
+proc_macro = true
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..78ba724
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,89 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{
+ parse::{self, Parse, ParseStream},
+ parse_macro_input,
+ punctuated::Punctuated,
+ Error, Expr, LitInt, Token,
+};
+
+#[derive(Clone)]
+struct Index {
+ index: usize,
+ value: Expr,
+}
+
+impl std::fmt::Debug for Index {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.index)
+ }
+}
+
+impl Parse for Index {
+ fn parse(input: ParseStream<'_>) -> parse::Result<Index> {
+ let index = input.parse::<LitInt>()?;
+ let index = index.base10_parse()?;
+ input.parse::<Token![=>]>()?;
+ let value = input.parse()?;
+ Ok(Index { index, value })
+ }
+}
+
+struct Map(Vec<Option<Index>>);
+impl Parse for Map {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let parsed = Punctuated::<Index, Token![,]>::parse_terminated(input)?;
+ let mut all = parsed.into_iter().collect::<Vec<_>>();
+ if all.len() == 0 {
+ return Err(input.error("no keys"));
+ }
+ all.sort_unstable_by(|a, b| a.index.cmp(&b.index));
+ let max = all[all.len() - 1].index;
+ let mut out: Vec<Option<Index>> = vec![None; max + 1];
+ for Index { value, index } in all {
+ let o = out.get_mut(index).unwrap();
+ match o {
+ Some(_) => {
+ // err.combine(Error::new_spanned(&v.value, "other duplicate key"));
+ return Err(Error::new_spanned(&value, "duplicate keys"));
+ }
+ None => *o = Some(Index { value, index }),
+ }
+ }
+ Ok(Map(out))
+ }
+}
+
+/// Easily make a `[Option<T>; N]`
+///
+/// ```
+/// # use amap::amap;
+/// #[derive(Debug, PartialEq)]
+/// enum Y {
+/// A,
+/// B,
+/// C,
+/// }
+/// static X: [Option<Y>; 46] = amap! {
+/// 2 => Y::A,
+/// 5 => Y::C,
+/// 45 => Y::B,
+/// };
+/// assert_eq!(X[45].as_ref().unwrap(), &Y::B);
+/// ```
+#[proc_macro]
+pub fn amap(input: TokenStream) -> TokenStream {
+ let map = parse_macro_input!(input as Map);
+ let map = map.0.iter().map(|index| {
+ if let Some(index) = index {
+ let v = &index.value;
+ quote!(Some(#v))
+ } else {
+ quote!(None)
+ }
+ });
+ quote! {
+ [#(#map), *]
+ }
+ .into()
+}