#![doc(
html_logo_url = "https://github.com/vertexclique/cuneiform/raw/master/img/cuneiform-logo.png"
)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![forbid(unsafe_code)]
extern crate proc_macro;
use self::proc_macro::TokenStream;
use quote::*;
use syn::parse::{Parse, ParseStream, Result};
use syn::{parse_macro_input, DeriveInput, Index, LitBool, LitInt, LitStr, Token};
mod detection;
mod slabs;
pub(crate) struct CuneiformArgs {
pub(crate) hermetic: bool,
pub(crate) slab: String,
pub(crate) force: isize,
}
impl CuneiformArgs {
fn new() -> Self {
CuneiformArgs {
hermetic: true,
slab: String::from(""),
force: !0,
}
}
fn with_hermetic(&mut self, hermetic: bool) {
self.hermetic = hermetic;
}
fn with_slab(&mut self, slab: String) {
self.slab = slab;
}
fn with_force(&mut self, force: isize) {
self.force = force;
}
}
mod cunei_keywords {
syn::custom_keyword!(hermetic);
syn::custom_keyword!(slab);
syn::custom_keyword!(force);
}
impl Parse for CuneiformArgs {
fn parse(input: ParseStream) -> Result<Self> {
let mut cargs = CuneiformArgs::new();
if input.parse::<cunei_keywords::hermetic>().is_ok() {
input.parse::<Token![=]>()?;
let hermetic: LitBool = input.parse()?;
cargs.with_hermetic(hermetic.value);
}
if input.parse::<cunei_keywords::slab>().is_ok() {
input.parse::<Token![=]>()?;
let slab: LitStr = input.parse()?;
cargs.with_slab(String::from(slab.value().as_str()));
}
if input.parse::<cunei_keywords::force>().is_ok() {
input.parse::<Token![=]>()?;
let force_lit: LitInt = input.parse()?;
let force = force_lit.base10_parse::<isize>()?;
cargs.with_force(force);
}
Ok(cargs)
}
}
#[proc_macro_attribute]
pub fn cuneiform(args: TokenStream, input: TokenStream) -> TokenStream {
let pargs = parse_macro_input!(args as CuneiformArgs);
let input = parse_macro_input!(input as DeriveInput);
let frep = crate::slabs::fetch(pargs);
let frep = Index::from(frep as usize);
TokenStream::from(quote! {
#[repr(align(#frep))]
#input
})
}
#[proc_macro_attribute]
pub fn boundary_size(_attr: TokenStream, _input: TokenStream) -> TokenStream {
let boundary = crate::slabs::fallbackless_slab_fetch();
TokenStream::from(quote! {
pub const BOUNDARY_SIZE: u8 = #boundary;
})
}