binaryninja/high_level_il/
token_emitter.rsuse std::ptr::NonNull;
use binaryninjacore_sys::*;
use crate::disassembly::{
DisassemblySettings, DisassemblyTextLine, InstructionTextToken, InstructionTextTokenContext,
InstructionTextTokenType,
};
use crate::high_level_il::HighLevelILFunction;
use crate::language_representation::{OperatorPrecedence, SymbolDisplayResult, SymbolDisplayType};
use crate::rc::{Array, Ref, RefCountable};
use crate::variable::Variable;
pub type ScopeType = BNScopeType;
pub type TokenEmitterExpr = BNTokenEmitterExpr;
pub type BraceRequirement = BNBraceRequirement;
#[derive(PartialEq, Eq, Hash)]
pub struct HighLevelILTokenEmitter {
handle: NonNull<BNHighLevelILTokenEmitter>,
}
impl HighLevelILTokenEmitter {
pub(crate) unsafe fn from_raw(handle: NonNull<BNHighLevelILTokenEmitter>) -> Self {
Self { handle }
}
pub fn current_tokens(&self) -> Array<InstructionTextToken> {
let mut count = 0;
let array =
unsafe { BNHighLevelILTokenEmitterGetCurrentTokens(self.handle.as_ptr(), &mut count) };
unsafe { Array::new(array, count, ()) }
}
pub fn lines(&self) -> Array<DisassemblyTextLine> {
let mut count = 0;
let array = unsafe { BNHighLevelILTokenEmitterGetLines(self.handle.as_ptr(), &mut count) };
unsafe { Array::new(array, count, ()) }
}
pub fn prepend_collapse_blank_indicator(&self) {
unsafe { BNHighLevelILTokenPrependCollapseBlankIndicator(self.handle.as_ptr()) };
}
pub fn prepend_collapse_indicator(&self, context: InstructionTextTokenContext, hash: u64) {
unsafe {
BNHighLevelILTokenPrependCollapseIndicator(self.handle.as_ptr(), context.into(), hash)
};
}
pub fn has_collapsible_regions(&self) -> bool {
unsafe { BNHighLevelILTokenEmitterHasCollapsableRegions(self.handle.as_ptr()) }
}
pub fn set_has_collapsible_regions(&self, state: bool) {
unsafe { BNHighLevelILTokenEmitterSetHasCollapsableRegions(self.handle.as_ptr(), state) };
}
pub fn append(&self, token: InstructionTextToken) {
let mut raw_token = InstructionTextToken::into_raw(token);
unsafe { BNHighLevelILTokenEmitterAppend(self.handle.as_ptr(), &mut raw_token) };
InstructionTextToken::free_raw(raw_token);
}
pub fn init_line(&self) {
unsafe { BNHighLevelILTokenEmitterInitLine(self.handle.as_ptr()) };
}
pub fn new_line(&self) {
unsafe { BNHighLevelILTokenEmitterNewLine(self.handle.as_ptr()) };
}
pub fn increase_indent(&self) {
unsafe { BNHighLevelILTokenEmitterIncreaseIndent(self.handle.as_ptr()) };
}
pub fn decrease_indent(&self) {
unsafe { BNHighLevelILTokenEmitterDecreaseIndent(self.handle.as_ptr()) };
}
pub fn scope_separator(&self) {
unsafe { BNHighLevelILTokenEmitterScopeSeparator(self.handle.as_ptr()) };
}
pub fn begin_scope(&self, ty: ScopeType) {
unsafe { BNHighLevelILTokenEmitterBeginScope(self.handle.as_ptr(), ty) };
}
pub fn end_scope(&self, ty: ScopeType) {
unsafe { BNHighLevelILTokenEmitterEndScope(self.handle.as_ptr(), ty) };
}
pub fn scope_continuation(&self, force_same_line: bool) {
unsafe {
BNHighLevelILTokenEmitterScopeContinuation(self.handle.as_ptr(), force_same_line)
};
}
pub fn finalize_scope(&self) {
unsafe { BNHighLevelILTokenEmitterFinalizeScope(self.handle.as_ptr()) };
}
pub fn no_indent_for_this_line(&self) {
unsafe { BNHighLevelILTokenEmitterNoIndentForThisLine(self.handle.as_ptr()) };
}
pub fn begin_force_zero_confidence(&self) {
unsafe { BNHighLevelILTokenEmitterBeginForceZeroConfidence(self.handle.as_ptr()) };
}
pub fn end_force_zero_confidence(&self) {
unsafe { BNHighLevelILTokenEmitterEndForceZeroConfidence(self.handle.as_ptr()) };
}
pub fn set_current_expr(&self, expr: TokenEmitterExpr) -> CurrentTokenEmitterExpr {
let previous_expr =
unsafe { BNHighLevelILTokenEmitterSetCurrentExpr(self.handle.as_ptr(), expr) };
CurrentTokenEmitterExpr::new(self.to_owned(), expr, previous_expr)
}
fn restore_current_expr(&self, expr: TokenEmitterExpr) {
unsafe { BNHighLevelILTokenEmitterRestoreCurrentExpr(self.handle.as_ptr(), expr) };
}
pub fn finalize(&self) {
unsafe { BNHighLevelILTokenEmitterFinalize(self.handle.as_ptr()) };
}
pub fn append_open_paren(&self) {
unsafe { BNHighLevelILTokenEmitterAppendOpenParen(self.handle.as_ptr()) };
}
pub fn append_close_paren(&self) {
unsafe { BNHighLevelILTokenEmitterAppendCloseParen(self.handle.as_ptr()) };
}
pub fn append_open_bracket(&self) {
unsafe { BNHighLevelILTokenEmitterAppendOpenBracket(self.handle.as_ptr()) };
}
pub fn append_close_bracket(&self) {
unsafe { BNHighLevelILTokenEmitterAppendCloseBracket(self.handle.as_ptr()) };
}
pub fn append_open_brace(&self) {
unsafe { BNHighLevelILTokenEmitterAppendOpenBrace(self.handle.as_ptr()) };
}
pub fn append_close_brace(&self) {
unsafe { BNHighLevelILTokenEmitterAppendCloseBrace(self.handle.as_ptr()) };
}
pub fn append_semicolon(&self) {
unsafe { BNHighLevelILTokenEmitterAppendSemicolon(self.handle.as_ptr()) };
}
pub fn set_brace_requirement(&self, required: BraceRequirement) {
unsafe { BNHighLevelILTokenEmitterSetBraceRequirement(self.handle.as_ptr(), required) };
}
pub fn set_braces_around_switch_cases(&self, braces: bool) {
unsafe {
BNHighLevelILTokenEmitterSetBracesAroundSwitchCases(self.handle.as_ptr(), braces)
};
}
pub fn set_default_braces_on_same_line(&self, same_line: bool) {
unsafe {
BNHighLevelILTokenEmitterSetDefaultBracesOnSameLine(self.handle.as_ptr(), same_line)
};
}
pub fn set_simple_scope_allowed(&self, allowed: bool) {
unsafe { BNHighLevelILTokenEmitterSetSimpleScopeAllowed(self.handle.as_ptr(), allowed) };
}
pub fn brace_requirement(&self) -> BraceRequirement {
unsafe { BNHighLevelILTokenEmitterGetBraceRequirement(self.handle.as_ptr()) }
}
pub fn has_braces_around_switch_cases(&self) -> bool {
unsafe { BNHighLevelILTokenEmitterHasBracesAroundSwitchCases(self.handle.as_ptr()) }
}
pub fn default_braces_on_same_line(&self) -> bool {
unsafe { BNHighLevelILTokenEmitterGetDefaultBracesOnSameLine(self.handle.as_ptr()) }
}
pub fn is_simple_scope_allowed(&self) -> bool {
unsafe { BNHighLevelILTokenEmitterIsSimpleScopeAllowed(self.handle.as_ptr()) }
}
pub fn append_size_token(&self, size: usize, ty: InstructionTextTokenType) {
unsafe { BNAddHighLevelILSizeToken(size, ty, self.handle.as_ptr()) }
}
pub fn append_float_size_token(&self, size: usize, ty: InstructionTextTokenType) {
unsafe { BNAddHighLevelILFloatSizeToken(size, ty, self.handle.as_ptr()) }
}
pub fn append_var_text_token(
&self,
func: &HighLevelILFunction,
var: Variable,
expr_index: usize,
size: usize,
) {
unsafe {
BNAddHighLevelILVarTextToken(
func.handle,
&BNVariable::from(var),
self.handle.as_ptr(),
expr_index,
size,
)
}
}
pub fn append_integer_text_token(
&self,
func: &HighLevelILFunction,
expr_index: usize,
val: i64,
size: usize,
) {
unsafe {
BNAddHighLevelILIntegerTextToken(
func.handle,
expr_index,
val,
size,
self.handle.as_ptr(),
)
}
}
pub fn append_array_index_token(
&self,
func: &HighLevelILFunction,
expr_index: usize,
val: i64,
size: usize,
address: Option<u64>,
) {
unsafe {
BNAddHighLevelILArrayIndexToken(
func.handle,
expr_index,
val,
size,
self.handle.as_ptr(),
address.unwrap_or(0),
)
}
}
pub fn append_pointer_text_token(
&self,
func: &HighLevelILFunction,
expr_index: usize,
val: i64,
settings: &DisassemblySettings,
symbol_display: SymbolDisplayType,
precedence: OperatorPrecedence,
allow_short_string: bool,
) -> SymbolDisplayResult {
unsafe {
BNAddHighLevelILPointerTextToken(
func.handle,
expr_index,
val,
self.handle.as_ptr(),
settings.handle,
symbol_display,
precedence,
allow_short_string,
)
}
}
pub fn append_constant_text_token(
&self,
func: &HighLevelILFunction,
expr_index: usize,
val: i64,
size: usize,
settings: &DisassemblySettings,
precedence: OperatorPrecedence,
) {
unsafe {
BNAddHighLevelILConstantTextToken(
func.handle,
expr_index,
val,
size,
self.handle.as_ptr(),
settings.handle,
precedence,
)
}
}
}
unsafe impl Send for HighLevelILTokenEmitter {}
unsafe impl Sync for HighLevelILTokenEmitter {}
unsafe impl RefCountable for HighLevelILTokenEmitter {
unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
let handle = BNNewHighLevelILTokenEmitterReference(handle.handle.as_ptr());
let handle = NonNull::new(handle).unwrap();
Ref::new(HighLevelILTokenEmitter { handle })
}
unsafe fn dec_ref(handle: &Self) {
BNFreeHighLevelILTokenEmitter(handle.handle.as_ptr())
}
}
impl ToOwned for HighLevelILTokenEmitter {
type Owned = Ref<Self>;
fn to_owned(&self) -> Self::Owned {
unsafe { RefCountable::inc_ref(self) }
}
}
pub struct CurrentTokenEmitterExpr {
pub emitter: Ref<HighLevelILTokenEmitter>,
pub expr: TokenEmitterExpr,
pub previous_expr: TokenEmitterExpr,
}
impl CurrentTokenEmitterExpr {
pub fn new(
emitter: Ref<HighLevelILTokenEmitter>,
expr: TokenEmitterExpr,
previous_expr: TokenEmitterExpr,
) -> Self {
Self {
emitter,
expr,
previous_expr,
}
}
}
impl Drop for CurrentTokenEmitterExpr {
fn drop(&mut self) {
self.emitter.restore_current_expr(self.previous_expr);
}
}