idalib 0.9.0+9.3.260327

Idiomatic bindings to IDA SDK
Documentation
use crate::ffi::ida::msg;
use crate::ffi::plugin::PlugModBridge;
use crate::idb::IDB;
use crate::{IDA, IDAError};

pub trait IDAPlugin: Sized + Send + Sync + 'static {
    fn init(ida: &mut IDA, idb: &mut IDB) -> Result<Self, IDAError>;

    fn run(&mut self, ida: &mut IDA, idb: &mut IDB, arg: usize) -> Result<(), IDAError>;

    fn term(&mut self, _ida: &mut IDA, _idb: &mut IDB) -> Result<(), IDAError> {
        Ok(())
    }
}

trait IDAPluginErased: Send + Sync {
    fn run(&mut self, ida: &mut IDA, idb: &mut IDB, arg: usize) -> Result<(), IDAError>;
    fn term(&mut self, ida: &mut IDA, idb: &mut IDB) -> Result<(), IDAError>;
}

impl<P: IDAPlugin> IDAPluginErased for P {
    fn run(&mut self, ida: &mut IDA, idb: &mut IDB, arg: usize) -> Result<(), IDAError> {
        IDAPlugin::run(self, ida, idb, arg)
    }

    fn term(&mut self, ida: &mut IDA, idb: &mut IDB) -> Result<(), IDAError> {
        IDAPlugin::term(self, ida, idb)
    }
}

#[doc(hidden)]
pub struct PlugmodWrapper {
    name: &'static str,
    plugin: Box<dyn IDAPluginErased>,
}

impl PlugmodWrapper {
    pub fn new(name: &'static str, plugin: impl IDAPlugin) -> Self {
        Self {
            name,
            plugin: Box::new(plugin),
        }
    }
}

impl PlugModBridge for PlugmodWrapper {
    fn run(&mut self, arg: usize) -> bool {
        let result = IDB::current().and_then(|mut idb| {
            let mut ida = IDA::new(&idb);
            self.plugin.run(&mut ida, &mut idb, arg)
        });
        match result {
            Ok(()) => true,
            Err(e) => {
                let _ = unsafe { msg(&format!("[{}] `run` failed: {e}\n", self.name)) };
                false
            }
        }
    }

    fn term(&mut self) {
        let result = IDB::current().and_then(|mut idb| {
            let mut ida = IDA::new(&idb);
            self.plugin.term(&mut ida, &mut idb)
        });
        if let Err(e) = result {
            let _ = unsafe { msg(&format!("[{}] `term` failed: {e}\n", self.name)) };
        }
    }
}