use alloc::borrow::Cow;
use libafl_bolts::{Error, Named, impl_serdeany};
use serde::{Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err;
use crate::{
HasMetadata,
executors::ExitKind,
feedbacks::{Feedback, StateInitializer},
};
pub const TRANSFERRED_FEEDBACK_NAME: Cow<'static, str> =
Cow::Borrowed("transferred_feedback_internal");
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub struct TransferringMetadata {
transferring: bool,
}
impl_serdeany!(TransferringMetadata);
impl TransferringMetadata {
pub fn set_transferring(&mut self, transferring: bool) {
self.transferring = transferring;
}
}
#[derive(Debug, Copy, Clone, Default)]
pub struct TransferredFeedback {
#[cfg(feature = "track_hit_feedbacks")]
last_result: Option<bool>,
}
impl Named for TransferredFeedback {
fn name(&self) -> &Cow<'static, str> {
&TRANSFERRED_FEEDBACK_NAME
}
}
impl<S> StateInitializer<S> for TransferredFeedback
where
S: HasMetadata,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
state.add_metadata(TransferringMetadata { transferring: true });
Ok(())
}
}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for TransferredFeedback
where
S: HasMetadata,
{
fn is_interesting(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &I,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error> {
let res = state.metadata::<TransferringMetadata>()?.transferring;
#[cfg(feature = "track_hit_feedbacks")]
{
self.last_result = Some(res);
}
Ok(res)
}
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
self.last_result.ok_or(premature_last_result_err())
}
}