sdb_debugger 0.2.2

Book: Building a Debugger. Rust port of C++ debugger sdb
Documentation
use super::breakpoint_site::IdType;
use super::sdb_error::SdbError;
use super::traits::MaybeRc;
use super::traits::StoppointTrait;
use super::types::VirtualAddress;
use std::rc::Weak;
use std::{cell::RefCell, rc::Rc};

#[derive(Default, Clone)]
pub struct StoppointCollection {
    stoppoints: Vec<Rc<dyn MaybeRc>>,
}

impl StoppointCollection {
    pub fn push_strong<T>(&mut self, bs: Rc<RefCell<T>>) -> Weak<RefCell<T>>
    where
        T: StoppointTrait + ?Sized,
        Rc<RefCell<T>>: MaybeRc,
    {
        let res = bs.clone();
        self.stoppoints.push(Rc::new(bs));
        Rc::downgrade(&res)
    }

    pub fn push_weak<T>(&mut self, bs: Weak<RefCell<T>>) -> Weak<RefCell<T>>
    where
        T: StoppointTrait + ?Sized,
        Weak<RefCell<T>>: MaybeRc,
    {
        let res = bs.upgrade().unwrap();
        self.stoppoints.push(Rc::new(bs));
        Rc::downgrade(&res)
    }

    pub fn contain_id(&self, id: IdType) -> bool {
        self.stoppoints
            .iter()
            .any(|t| t.get_rc().borrow().id() == id)
    }

    pub fn contains_address(&self, address: VirtualAddress) -> bool {
        self.stoppoints
            .iter()
            .any(|t| t.get_rc().borrow().at_address(address))
    }

    pub fn enabled_breakpoint_at_address(&self, address: VirtualAddress) -> bool {
        self.contains_address(address)
            && self.get_by_address(address).unwrap().borrow().is_enabled()
    }

    pub fn get_by_id(&self, id: IdType) -> Result<Rc<RefCell<dyn StoppointTrait>>, SdbError> {
        match self
            .stoppoints
            .iter()
            .find(|t| t.get_rc().borrow().id() == id)
        {
            Some(v) => Ok(v.get_rc()),
            None => SdbError::err("Invalid stoppoint id"),
        }
    }

    pub fn get_by_address(
        &self,
        address: VirtualAddress,
    ) -> Result<Rc<RefCell<dyn StoppointTrait>>, SdbError> {
        match self
            .stoppoints
            .iter()
            .find(|t| t.get_rc().borrow().at_address(address))
        {
            Some(v) => Ok(v.get_rc()),
            None => SdbError::err("Invalid stoppoint id"),
        }
    }

    pub fn remove_by_id(&mut self, id: IdType) -> Result<(), SdbError> {
        if let Some(pos) = self
            .stoppoints
            .iter()
            .position(|s| s.get_rc().borrow().id() == id)
        {
            self.stoppoints[pos].get_rc().borrow_mut().disable()?;
            self.stoppoints.remove(pos);
        }
        Ok(())
    }

    pub fn remove_by_address(&mut self, address: VirtualAddress) -> Result<(), SdbError> {
        if let Some(pos) = self
            .stoppoints
            .iter()
            .position(|s| s.get_rc().borrow().at_address(address))
        {
            self.stoppoints[pos].get_rc().borrow_mut().disable()?;
            self.stoppoints.remove(pos);
        }
        Ok(())
    }

    pub fn for_each_mut(&mut self, mut f: impl FnMut(&Rc<RefCell<dyn StoppointTrait>>)) {
        self.stoppoints.iter_mut().for_each(|s| f(&s.get_rc()));
    }

    pub fn for_each(&self, f: impl Fn(&Rc<RefCell<dyn StoppointTrait>>)) {
        self.stoppoints
            .iter()
            .map(|s| s.get_rc())
            .for_each(|s| f(&s));
    }

    pub fn size(&self) -> usize {
        self.stoppoints.len()
    }

    pub fn empty(&self) -> bool {
        self.stoppoints.is_empty()
    }

    pub fn get_in_region(
        &self,
        low: VirtualAddress,
        high: VirtualAddress,
    ) -> Vec<Rc<RefCell<dyn StoppointTrait>>> {
        let mut ret: Vec<Rc<RefCell<dyn StoppointTrait>>> = vec![];
        for site in self.stoppoints.iter() {
            if site.get_rc().borrow().in_range(low, high) {
                ret.push(site.get_rc());
            }
        }
        ret
    }

    pub fn iter(&self) -> impl Iterator<Item = Rc<RefCell<dyn StoppointTrait>>> {
        self.stoppoints.iter().map(|s| s.get_rc())
    }
}