use std::collections::HashMap;
use syn::{Attribute, Error, Ident, Token, braced, parse::Parse, visit_mut::VisitMut};
use crate::vis::Vis;
pub struct OverrideItem {
pub attrs: Vec<Attribute>,
pub vis: Vis,
pub item_ident: Ident,
pub new_ident: Option<Ident>,
}
pub struct OverrideBlock {
pub items: HashMap<Ident, OverrideItem>,
}
impl OverrideBlock {
pub fn new_init() -> Self {
macro_rules! items {
($(
$(
#[$attr:meta]
)*
$vis:vis
$name:ident
)*) => {
HashMap::from([
$(
{
let ident: Ident = syn::parse_quote!($name);
(
ident.clone(),
OverrideItem {
attrs: syn::parse_quote!($(#[$attr])*),
vis: syn::parse_quote!($vis),
item_ident: ident,
new_ident: None,
}
)
},
)*
])
};
}
Self {
items: items![
pub new
pub none
pub all
pub union
pub union_without
pub try_find
pub find
pub find_or
pub find_or_none
pub count_ones
pub count_zeros
pub get
pub set
pub swap
pub from_index
pub leading_zeros
pub trailing_zeros
pub leading_ones
pub trailing_ones
pub add
pub add_if
pub add_all
pub add_all_if
pub remove
pub remove_if
pub remove_all
pub remove_all_if
pub with
pub with_if
pub with_all
pub with_all_if
pub without
pub without_if
pub without_all
pub without_all_if
pub has_all
pub has_none
pub has_any
pub has_some
pub as_slice
pub as_mut_slice
pub into_inner
pub as_bytes
pub as_mut_bytes
pub to_be_bytes
pub from_be_bytes
pub to_le_bytes
pub from_le_bytes
pub to_ne_bytes
pub from_ne_bytes
pub decompose
pub compose
pub not_assign
pub not
pub and_assign
pub and
pub or_assign
pub or
pub xor_assign
pub xor
pub nand_assign
pub nand
pub nor_assign
pub nor
pub xnor_assign
pub xnor
pub imply_assign
pub imply
pub nimply_assign
pub nimply
pub eq
pub ne
pub is_empty
pub is_not_empty
pub len
pub is_valid
]
}
}
#[inline(always)]
fn insert(&mut self, key: Ident, item: OverrideItem) -> Option<OverrideItem> {
self.items.insert(key, item)
}
pub fn get_alt(&self, key: &Ident) -> Option<&Ident> {
if let Some(item) = self.items.get(key) {
item.new_ident.as_ref()
} else {
None
}
}
pub fn get_vis(&self, key: &Ident) -> &Vis {
if let Some(item) = self.items.get(key) {
&item.vis
} else {
panic!("Identifier not found.");
}
}
}
impl Parse for OverrideItem {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
item_ident: input.parse()?,
new_ident: {
if input.peek(Token![:]) {
input.parse::<Token![:]>()?;
Some(input.parse()?)
} else {
None
}
}
})
}
}
impl Parse for OverrideBlock {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut items = OverrideBlock::new_init();
if !input.peek(Token![override]) {
return Ok(items);
}
input.parse::<Token![override]>()?;
let block;
braced!(block in input);
while !block.is_empty() {
let item = block.parse::<OverrideItem>()?;
let key = item.item_ident.clone();
let ident_span = item.item_ident.span();
if items.insert(key, item).is_none() {
return Err(Error::new(ident_span, "Unexpected override item."));
}
}
Ok(items)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum OverrideStage {
Functions,
Operators,
}
pub struct Overrider<'a> {
pub overrides: &'a OverrideBlock,
pub stage: OverrideStage,
}
impl<'a> VisitMut for Overrider<'a> {
fn visit_item_fn_mut(&mut self, i: &mut syn::ItemFn) {
if matches!(self.stage, OverrideStage::Functions) {
if let Some(item) = self.overrides.items.get(&i.sig.ident) {
i.attrs.extend(item.attrs.iter().cloned());
let vis = item.vis.resolve(Some(&i.vis));
i.vis = vis;
if let Some(alt) = &item.new_ident {
i.sig.ident = alt.clone();
}
}
}
syn::visit_mut::visit_item_fn_mut(self, i);
}
fn visit_path_mut(&mut self, i: &mut syn::Path) {
if i.segments.len() < 2 {
syn::visit_mut::visit_path_mut(self, i);
return;
}
let first = &i.segments[0].ident;
if first != "Self" {
syn::visit_mut::visit_path_mut(self, i);
return;
}
let second = &mut i.segments[1].ident;
if let Some(new_ident) = self.overrides.get_alt(second) {
*second = new_ident.clone();
}
syn::visit_mut::visit_path_mut(self, i);
}
fn visit_expr_method_call_mut(&mut self, i: &mut syn::ExprMethodCall) {
if let syn::Expr::Path(exp) = &mut *i.receiver {
if exp.path.segments.len() < 1 {
syn::visit_mut::visit_expr_method_call_mut(self, i);
return;
}
let first = &exp.path.segments[0].ident;
let guard = const { ["self", "builder"] }
.into_iter()
.all(|name| {
first != name
});
if guard {
syn::visit_mut::visit_expr_method_call_mut(self, i);
return;
}
if let Some(new_ident) = self.overrides.get_alt(&i.method) {
i.method = new_ident.clone();
}
}
syn::visit_mut::visit_expr_method_call_mut(self, i);
}
}