use proc_macro2::TokenStream;
use quote::quote;
use syn::{Ident, LitInt, Type};
pub fn impl_prim_int(
struct_name: &Ident,
ty: &Type,
shift: &Option<LitInt>,
masking: &TokenStream,
) -> TokenStream {
let shl_shift;
let shr_shift;
let sub_shift;
let one_mask;
let rotate_left;
let rotate_right;
if let Some(shift) = shift {
shl_shift = quote! { << #shift };
shr_shift = quote! { >> #shift };
sub_shift = quote! { - #shift as u32 };
one_mask = quote! { | (1 << #shift) - 1 };
rotate_left = quote! {
{
let up = self.0.unsigned_shl(n);
let down = self.0.rotate_left(n) & ((1 << #shift) - 1);
let down = down.unsigned_shl(#shift);
up | down
}
};
rotate_right = quote! {
{
let up = self.0.unsigned_shr(n) & !((1 << #shift) - 1);
let down = self.0.unsigned_shr(#shift).rotate_right(n);
let down = down #masking;
up | down
}
};
} else {
shl_shift = quote! {};
shr_shift = quote! {};
sub_shift = quote! {};
one_mask = quote! {};
rotate_left = quote! {
self.0.rotate_left(n)
};
rotate_right = quote! {
self.0.rotate_right(n)
};
}
quote! {
impl num_traits::int::PrimInt for #struct_name {
fn count_ones(self) -> u32 {
<#ty as num_traits::int::PrimInt>::count_ones(self.0)
}
fn count_zeros(self) -> u32 {
<#ty as num_traits::int::PrimInt>::count_zeros(self.0) #sub_shift
}
fn leading_zeros(self) -> u32 {
<#ty as num_traits::int::PrimInt>::leading_zeros(self.0 #one_mask)
}
fn trailing_zeros(self) -> u32 {
<#ty as num_traits::int::PrimInt>::trailing_zeros(self.0 #shr_shift)
}
fn rotate_left(self, n: u32) -> Self {
let result = #rotate_left;
Self::from_bits(result as #ty)
}
fn rotate_right(self, n: u32) -> Self {
let result = #rotate_right;
Self::from_bits(result as #ty)
}
fn signed_shl(self, n: u32) -> Self {
Self::from_bits(self.0.signed_shl(n) #masking)
}
fn signed_shr(self, n: u32) -> Self {
Self::from_bits(self.0.signed_shr(n) #masking)
}
fn unsigned_shl(self, n: u32) -> Self {
Self::from_bits(self.0.unsigned_shl(n) #masking)
}
fn unsigned_shr(self, n: u32) -> Self {
Self::from_bits(self.0.unsigned_shr(n) #masking)
}
fn swap_bytes(self) -> Self {
unimplemented!()
}
fn from_be(x: Self) -> Self {
unimplemented!()
}
fn from_le(x: Self) -> Self {
unimplemented!()
}
fn to_be(self) -> Self {
unimplemented!()
}
fn to_le(self) -> Self {
unimplemented!()
}
fn pow(self, exp: u32) -> Self {
Self::from_bits(<#ty as num_traits::int::PrimInt>::pow(self.0 #shr_shift, exp) #shl_shift)
}
fn leading_ones(self) -> u32 {
<#ty as num_traits::int::PrimInt>::leading_ones(self.0)
}
fn trailing_ones(self) -> u32 {
<#ty as num_traits::int::PrimInt>::trailing_ones(self.0 #shr_shift)
}
fn reverse_bits(self) -> Self {
Self::from_bits(<#ty as num_traits::int::PrimInt>::reverse_bits(self.0) #shl_shift)
}
}
}
}