use proc_macro2::TokenStream;
use quote::quote;
use syn::parse::{Parse, ParseStream};
use syn::{Block, Expr, Token};
pub struct Branch {
cond: Expr,
then_branch: Block,
else_branch: Block,
}
impl Parse for Branch {
fn parse(input: ParseStream) -> syn::Result<Self> {
let cond = Expr::parse_without_eager_brace(input)?;
let then_branch = input.parse()?;
input.parse::<Token![else]>()?;
let else_branch = input.parse()?;
Ok(Self {
cond,
then_branch,
else_branch,
})
}
}
impl Branch {
pub fn obscure(self, site_salt: u64) -> TokenStream {
let Self {
cond,
then_branch,
else_branch,
} = self;
let mask = site_salt as u8;
let target = mask ^ 1;
quote! {
{
let __boo_mask: u8 = ::core::hint::black_box(#mask);
let __boo_target: u8 = ::core::hint::black_box(#target);
let __boo_selector: u8 = ::core::hint::black_box(((#cond) as u8) ^ __boo_mask);
if __boo_selector == __boo_target #then_branch else #else_branch
}
}
}
}