use crate::debugger::BreakpointView;
use crate::debugger::Debugger;
use crate::debugger::Error;
use crate::debugger::address::Address;
#[derive(Debug, Clone, PartialEq)]
pub enum BreakpointIdentity {
Address(usize),
Line(String, u64),
Function(String),
Number(u32),
}
#[derive(Debug, Clone, PartialEq)]
pub enum Command {
Add(BreakpointIdentity),
Remove(BreakpointIdentity),
Info,
AddDeferred(BreakpointIdentity),
}
impl Command {
pub fn identity(&self) -> Option<BreakpointIdentity> {
match self {
Command::Add(b) => Some(b.clone()),
Command::Remove(b) => Some(b.clone()),
Command::Info => None,
Command::AddDeferred(b) => Some(b.clone()),
}
}
}
pub struct Handler<'a> {
dbg: &'a mut Debugger,
}
pub enum ExecutionResult<'a> {
New(Vec<BreakpointView<'a>>),
Removed(Vec<BreakpointView<'a>>),
Dump(Vec<BreakpointView<'a>>),
AddDeferred,
}
impl<'a> Handler<'a> {
pub fn new(debugger: &'a mut Debugger) -> Self {
Self { dbg: debugger }
}
pub fn handle(&mut self, cmd: &Command) -> Result<ExecutionResult<'_>, Error> {
let result = match cmd {
Command::Add(brkpt) => {
let res = match brkpt {
BreakpointIdentity::Address(addr) => {
vec![self.dbg.set_breakpoint_at_addr((*addr).into())?]
}
BreakpointIdentity::Line(file, line) => {
self.dbg.set_breakpoint_at_line(file, *line)?
}
BreakpointIdentity::Function(func_name) => {
self.dbg.set_breakpoint_at_fn(func_name)?
}
BreakpointIdentity::Number(_) => {
unreachable!()
}
};
ExecutionResult::New(res)
}
Command::Remove(brkpt) => {
let res = match brkpt {
BreakpointIdentity::Address(addr) => self
.dbg
.remove_breakpoint(Address::Relocated((*addr).into()))?
.map(|brkpt| vec![brkpt])
.unwrap_or_default(),
BreakpointIdentity::Line(file, line) => {
self.dbg.remove_breakpoint_at_line(file, *line)?
}
BreakpointIdentity::Function(func_name) => {
self.dbg.remove_breakpoint_at_fn(func_name)?
}
BreakpointIdentity::Number(number) => self
.dbg
.remove_breakpoint_by_number(*number)?
.map(|brkpt| vec![brkpt])
.unwrap_or_default(),
};
ExecutionResult::Removed(res)
}
Command::Info => ExecutionResult::Dump(self.dbg.breakpoints_snapshot()),
Command::AddDeferred(brkpt) => {
match brkpt {
BreakpointIdentity::Address(addr) => {
self.dbg.add_deferred_at_addr((*addr).into())
}
BreakpointIdentity::Line(file, line) => {
self.dbg.add_deferred_at_line(file, *line)
}
BreakpointIdentity::Function(function) => {
self.dbg.add_deferred_at_function(function)
}
BreakpointIdentity::Number(_) => {
unreachable!()
}
};
ExecutionResult::AddDeferred
}
};
Ok(result)
}
}