metaemu_intrinsics/
lib.rs

1use fugue::ir::il::pcode::Operand;
2use fugue::ir::AddressValue;
3
4use metaemu_state::State;
5
6use std::collections::HashMap;
7
8use thiserror::Error;
9
10#[derive(Debug, Error)]
11pub enum Error<E: std::error::Error + 'static> {
12    #[error(transparent)]
13    State(E),
14    #[error(transparent)]
15    Other(#[from] anyhow::Error),
16}
17
18impl<E> Error<E>
19where
20    E: std::error::Error + 'static,
21{
22    pub fn state(error: E) -> Self {
23        Self::State(error)
24    }
25}
26
27#[derive(Clone)]
28pub enum IntrinsicAction<O> {
29    Pass,
30    Branch(AddressValue),
31    Halt(O),
32}
33
34pub trait IntrinsicBehaviour: dyn_clone::DynClone {
35    type Outcome;
36    type State: State;
37
38    fn intrinsic(&self) -> &str;
39
40    fn initialise(
41        &mut self,
42        #[allow(unused)] state: &Self::State,
43    ) -> Result<(), Error<<Self::State as State>::Error>> {
44        Ok(())
45    }
46
47    fn handle_intrinsic(
48        &mut self,
49        state: &mut Self::State,
50        inputs: &[Operand],
51        output: Option<&Operand>,
52    ) -> Result<IntrinsicAction<Self::Outcome>, Error<<Self::State as State>::Error>>;
53}
54dyn_clone::clone_trait_object!(<Outcome, State> IntrinsicBehaviour<Outcome=Outcome, State=State> where State: metaemu_state::State);
55
56#[derive(Clone)]
57pub struct IntrinsicHandler<O, S: State> {
58    handlers: HashMap<String, Box<dyn IntrinsicBehaviour<Outcome = O, State = S>>>,
59    default_action: IntrinsicAction<O>,
60}
61
62impl<O: Clone, S: State> Default for IntrinsicHandler<O, S> {
63    fn default() -> Self {
64        Self::new()
65    }
66}
67
68impl<O: Clone, S: State> IntrinsicHandler<O, S> {
69    pub fn new() -> Self {
70        Self::new_with(IntrinsicAction::Pass)
71    }
72
73    pub fn new_with(default_action: IntrinsicAction<O>) -> Self {
74        Self {
75            handlers: HashMap::new(),
76            default_action,
77        }
78    }
79
80    pub fn register<IN: IntrinsicBehaviour<Outcome = O, State = S> + 'static>(
81        &mut self,
82        behaviour: IN,
83        state: &S,
84    ) -> Result<(), Error<S::Error>> {
85        let mut behaviour = behaviour;
86        behaviour.initialise(state)?;
87
88        let name = behaviour.intrinsic().to_owned();
89
90        self.handlers.insert(name, Box::new(behaviour));
91
92        Ok(())
93    }
94
95    pub fn handle(
96        &mut self,
97        name: &str,
98        state: &mut S,
99        inputs: &[Operand],
100        output: Option<&Operand>,
101    ) -> Result<IntrinsicAction<O>, Error<S::Error>> {
102        if let Some(handler) = self.handlers.get_mut(name) {
103            handler.handle_intrinsic(state, inputs, output)
104        } else {
105            Ok(self.default_action.clone())
106        }
107    }
108}