Archived
3
0

initial commit

This commit is contained in:
2025-03-04 11:22:53 +01:00
commit 5bb655b7de
32 changed files with 6229 additions and 0 deletions

1
lib/inferium/proc/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
target/

7
lib/inferium/proc/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "proc"
version = "0.1.0"

View File

@@ -0,0 +1,9 @@
[package]
name = "proc"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]

View File

@@ -0,0 +1,175 @@
use proc_macro::{Delimiter, TokenStream, TokenTree};
extern crate proc_macro;
#[proc_macro_derive(AutoimplHkeys)]
pub fn autoimpl_hkeys(item: TokenStream) -> TokenStream {
let mut iter = item.into_iter();
let data = autoimpl_names_get_idents(&mut iter).expect("could not parse the name enum");
let obj_ident = data.obj_ident;
let mut cases_from = String::new();
let mut cases_into = String::new();
let mut cases_text = String::new();
let mut cases_display = String::new();
for entry in data.names {
let entry_transformed = autoimpl_hkeys_transform(&entry);
cases_from.push_str(&format!("{entry_transformed:?} => Self::{entry},\n"));
cases_into.push_str(&format!(
"{obj_ident}::{entry} => String::from({entry_transformed:?}),\n"
));
cases_text.push_str(&format!("{obj_ident}::{entry} => b{entry_transformed:?},\n"));
cases_display.push_str(
&format!("{obj_ident}::{entry} => write!(f, {entry_transformed:?}),")
);
}
format!("impl From<&str> for {obj_ident} {{
fn from(s: &str) -> Self {{
match s.to_lowercase().as_str() {{
{cases_from}
v => Self::OTHER(v.to_string()),
}}
}}
}}
impl From<{obj_ident}> for String {{
fn from(val: {obj_ident}) -> Self {{
match val {{
{cases_into}
{obj_ident}::OTHER(v) => v.clone(),
}}
}}
}}
impl {obj_ident} {{
pub(crate) fn text(&self) -> &[u8] {{
match self {{
{cases_text}
Self::OTHER(v) => v.as_bytes(),
}}
}}
}}
impl std::fmt::Display for {obj_ident} {{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {{
match self {{
{cases_display}
Self::OTHER(v) => write!(f, \"{{v}}\"),
}}
}}
}}").parse().expect("could not parse the created autoimpl")
}
#[proc_macro_derive(AutoimplMethods)]
pub fn autoimpl_methods(item: TokenStream) -> TokenStream {
let mut iter = item.into_iter();
let data = autoimpl_names_get_idents(&mut iter).expect("could not parse the name enum");
let obj_ident = data.obj_ident;
let mut cases_from = String::new();
let mut cases_into = String::new();
let mut cases_text = String::new();
for entry in data.names {
cases_from.push_str(&format!("{entry:?} => Ok(Self::{entry}),\n"));
cases_into.push_str(&format!("{obj_ident}::{entry} => {entry:?},\n"));
cases_text.push_str(&format!("{obj_ident}::{entry} => b{entry:?},\n"));
}
format!("impl std::str::FromStr for {obj_ident} {{
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {{
match s {{
{cases_from}
_ => Err(()),
}}
}}
}}
impl From<{obj_ident}> for &'static str {{
fn from(val: {obj_ident}) -> Self {{
match val {{
{cases_into}
}}
}}
}}
impl {obj_ident} {{
pub(crate) fn text(&self) -> &'static [u8] {{
match self {{
{cases_text}
}}
}}
}}").parse().expect("could not parse the created autoimpl")
}
fn autoimpl_hkeys_transform(name: &str) -> String {
name.to_lowercase().replace("_", "-")
}
macro_rules! get_tok {
(req $($rest:tt)+) => {
get_tok!($($rest)+)?.ok_or(())?
};
($iter:ident == $t:ident $val:literal) => {{
get_tok!($t $iter).map(
|v| v.map(|v| v.to_string() == $val)
).unwrap_or_else(|_| Some(false))
}};
($iter:ident != $t:ident $val:literal) => {
get_tok!($t $iter).map(
|v| v.map(|v| v.to_string() != $val)
).unwrap_or_else(|_| Some(false))
};
($t:ident $iter:ident) => {{
match $iter.next() {
Some(TokenTree::$t(val)) => Ok(Some(val)),
None => Ok(None),
_ => Err(()),
}
}};
}
struct NameData {
obj_ident: String,
names: Vec<String>,
}
fn autoimpl_names_get_idents<I: Iterator<Item = TokenTree>>(
iter: &mut I
) -> Result<NameData, ()> {
while let Some(is_enum_start) = get_tok!(iter == Ident "enum") {
if is_enum_start {
break;
}
}
let obj_ident = get_tok!(req Ident iter).to_string();
let mut iter = {
let group = get_tok!(req Group iter);
if group.delimiter() != Delimiter::Brace {
return Err(());
}
group.stream().into_iter()
};
let mut names = Vec::new();
loop {
let Some(name) = get_tok!(Ident iter)? else {
break;
};
if name.to_string() == "OTHER" {
break;
}
names.push(name.to_string());
match get_tok!(iter == Punct ",") {
Some(true) => {},
Some(false) => Err(())?,
None => break,
}
}
Ok(NameData { obj_ident, names })
}