pub mod map;
pub use map::*;
pub mod cmp;
pub use cmp::*;
#[cfg(feature = "std")]
pub mod stdio;
#[cfg(feature = "std")]
pub use stdio::{StdErrObserver, StdOutObserver};
#[cfg(feature = "std")]
pub mod stacktrace;
#[cfg(feature = "std")]
pub use stacktrace::*;
pub mod concolic;
pub mod value;
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::{fmt::Debug, time::Duration};
use serde::{Deserialize, Serialize};
pub use value::*;
use crate::{
bolts::{
current_time,
ownedref::OwnedMutPtr,
tuples::{MatchName, Named},
},
executors::ExitKind,
inputs::UsesInput,
state::UsesState,
Error,
};
pub trait Observer<S>: Named + Debug
where
S: UsesInput,
{
#[inline]
fn flush(&mut self) -> Result<(), Error> {
Ok(())
}
#[inline]
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
Ok(())
}
#[inline]
fn post_exec(
&mut self,
_state: &mut S,
_input: &S::Input,
_exit_kind: &ExitKind,
) -> Result<(), Error> {
Ok(())
}
#[inline]
fn pre_exec_child(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
Ok(())
}
#[inline]
fn post_exec_child(
&mut self,
_state: &mut S,
_input: &S::Input,
_exit_kind: &ExitKind,
) -> Result<(), Error> {
Ok(())
}
#[inline]
fn observes_stdout(&self) -> bool {
false
}
#[inline]
fn observes_stderr(&self) -> bool {
false
}
#[inline]
#[allow(unused_variables)]
fn observe_stdout(&mut self, stdout: &[u8]) {}
#[inline]
#[allow(unused_variables)]
fn observe_stderr(&mut self, stderr: &[u8]) {}
}
pub trait UsesObservers: UsesState {
type Observers: ObserversTuple<Self::State>;
}
pub trait ObserversTuple<S>: MatchName + Debug
where
S: UsesInput,
{
fn pre_exec_all(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error>;
fn post_exec_all(
&mut self,
state: &mut S,
input: &S::Input,
exit_kind: &ExitKind,
) -> Result<(), Error>;
fn pre_exec_child_all(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error>;
fn post_exec_child_all(
&mut self,
state: &mut S,
input: &S::Input,
exit_kind: &ExitKind,
) -> Result<(), Error>;
fn observes_stdout(&self) -> bool;
fn observes_stderr(&self) -> bool;
fn observe_stdout(&mut self, stdout: &[u8]);
fn observe_stderr(&mut self, stderr: &[u8]);
}
impl<S> ObserversTuple<S> for ()
where
S: UsesInput,
{
fn pre_exec_all(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
Ok(())
}
fn post_exec_all(
&mut self,
_state: &mut S,
_input: &S::Input,
_exit_kind: &ExitKind,
) -> Result<(), Error> {
Ok(())
}
fn pre_exec_child_all(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
Ok(())
}
fn post_exec_child_all(
&mut self,
_state: &mut S,
_input: &S::Input,
_exit_kind: &ExitKind,
) -> Result<(), Error> {
Ok(())
}
#[inline]
fn observes_stdout(&self) -> bool {
false
}
#[inline]
fn observes_stderr(&self) -> bool {
false
}
#[inline]
#[allow(unused_variables)]
fn observe_stdout(&mut self, stdout: &[u8]) {}
#[inline]
#[allow(unused_variables)]
fn observe_stderr(&mut self, stderr: &[u8]) {}
}
impl<Head, Tail, S> ObserversTuple<S> for (Head, Tail)
where
Head: Observer<S>,
Tail: ObserversTuple<S>,
S: UsesInput,
{
fn pre_exec_all(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error> {
self.0.pre_exec(state, input)?;
self.1.pre_exec_all(state, input)
}
fn post_exec_all(
&mut self,
state: &mut S,
input: &S::Input,
exit_kind: &ExitKind,
) -> Result<(), Error> {
self.0.post_exec(state, input, exit_kind)?;
self.1.post_exec_all(state, input, exit_kind)
}
fn pre_exec_child_all(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error> {
self.0.pre_exec_child(state, input)?;
self.1.pre_exec_child_all(state, input)
}
fn post_exec_child_all(
&mut self,
state: &mut S,
input: &S::Input,
exit_kind: &ExitKind,
) -> Result<(), Error> {
self.0.post_exec_child(state, input, exit_kind)?;
self.1.post_exec_child_all(state, input, exit_kind)
}
#[inline]
fn observes_stdout(&self) -> bool {
self.0.observes_stdout() || self.1.observes_stdout()
}
#[inline]
fn observes_stderr(&self) -> bool {
self.0.observes_stderr() || self.1.observes_stderr()
}
#[inline]
fn observe_stdout(&mut self, stdout: &[u8]) {
self.0.observe_stdout(stdout);
self.1.observe_stdout(stdout);
}
#[inline]
fn observe_stderr(&mut self, stderr: &[u8]) {
self.0.observe_stderr(stderr);
self.1.observe_stderr(stderr);
}
}
pub trait ObserverWithHashField {
fn hash(&self) -> Option<u64>;
}
#[allow(unused_variables)]
pub trait DifferentialObserver<OTA, OTB, S>: Observer<S>
where
OTA: ObserversTuple<S>,
OTB: ObserversTuple<S>,
S: UsesInput,
{
fn pre_observe_first(&mut self, observers: &mut OTA) -> Result<(), Error> {
Ok(())
}
fn post_observe_first(&mut self, observers: &mut OTA) -> Result<(), Error> {
Ok(())
}
fn pre_observe_second(&mut self, observers: &mut OTB) -> Result<(), Error> {
Ok(())
}
fn post_observe_second(&mut self, observers: &mut OTB) -> Result<(), Error> {
Ok(())
}
}
pub trait DifferentialObserversTuple<OTA, OTB, S>: ObserversTuple<S>
where
OTA: ObserversTuple<S>,
OTB: ObserversTuple<S>,
S: UsesInput,
{
fn pre_observe_first_all(&mut self, observers: &mut OTA) -> Result<(), Error>;
fn post_observe_first_all(&mut self, observers: &mut OTA) -> Result<(), Error>;
fn pre_observe_second_all(&mut self, observers: &mut OTB) -> Result<(), Error>;
fn post_observe_second_all(&mut self, observers: &mut OTB) -> Result<(), Error>;
}
impl<OTA, OTB, S> DifferentialObserversTuple<OTA, OTB, S> for ()
where
OTA: ObserversTuple<S>,
OTB: ObserversTuple<S>,
S: UsesInput,
{
fn pre_observe_first_all(&mut self, _: &mut OTA) -> Result<(), Error> {
Ok(())
}
fn post_observe_first_all(&mut self, _: &mut OTA) -> Result<(), Error> {
Ok(())
}
fn pre_observe_second_all(&mut self, _: &mut OTB) -> Result<(), Error> {
Ok(())
}
fn post_observe_second_all(&mut self, _: &mut OTB) -> Result<(), Error> {
Ok(())
}
}
impl<Head, Tail, OTA, OTB, S> DifferentialObserversTuple<OTA, OTB, S> for (Head, Tail)
where
Head: DifferentialObserver<OTA, OTB, S>,
Tail: DifferentialObserversTuple<OTA, OTB, S>,
OTA: ObserversTuple<S>,
OTB: ObserversTuple<S>,
S: UsesInput,
{
fn pre_observe_first_all(&mut self, observers: &mut OTA) -> Result<(), Error> {
self.0.pre_observe_first(observers)?;
self.1.pre_observe_first_all(observers)
}
fn post_observe_first_all(&mut self, observers: &mut OTA) -> Result<(), Error> {
self.0.post_observe_first(observers)?;
self.1.post_observe_first_all(observers)
}
fn pre_observe_second_all(&mut self, observers: &mut OTB) -> Result<(), Error> {
self.0.pre_observe_second(observers)?;
self.1.pre_observe_second_all(observers)
}
fn post_observe_second_all(&mut self, observers: &mut OTB) -> Result<(), Error> {
self.0.post_observe_second(observers)?;
self.1.post_observe_second_all(observers)
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TimeObserver {
name: String,
start_time: Duration,
last_runtime: Option<Duration>,
}
impl TimeObserver {
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
start_time: Duration::from_secs(0),
last_runtime: None,
}
}
#[must_use]
pub fn last_runtime(&self) -> &Option<Duration> {
&self.last_runtime
}
}
impl<S> Observer<S> for TimeObserver
where
S: UsesInput,
{
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
self.last_runtime = None;
self.start_time = current_time();
Ok(())
}
fn post_exec(
&mut self,
_state: &mut S,
_input: &S::Input,
_exit_kind: &ExitKind,
) -> Result<(), Error> {
self.last_runtime = current_time().checked_sub(self.start_time);
Ok(())
}
}
impl Named for TimeObserver {
fn name(&self) -> &str {
&self.name
}
}
impl<OTA, OTB, S> DifferentialObserver<OTA, OTB, S> for TimeObserver
where
OTA: ObserversTuple<S>,
OTB: ObserversTuple<S>,
S: UsesInput,
{
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
#[allow(clippy::unsafe_derive_deserialize)]
pub struct ListObserver<T>
where
T: Debug + Serialize,
{
name: String,
list: OwnedMutPtr<Vec<T>>,
}
impl<T> ListObserver<T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
#[must_use]
pub unsafe fn new(name: &'static str, list: *mut Vec<T>) -> Self {
Self {
name: name.to_string(),
list: OwnedMutPtr::Ptr(list),
}
}
#[must_use]
pub fn list(&self) -> &Vec<T> {
self.list.as_ref()
}
#[must_use]
pub fn list_mut(&mut self) -> &mut Vec<T> {
self.list.as_mut()
}
}
impl<S, T> Observer<S> for ListObserver<T>
where
S: UsesInput,
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
self.list.as_mut().clear();
Ok(())
}
}
impl<T> Named for ListObserver<T>
where
T: Debug + Serialize + serde::de::DeserializeOwned,
{
fn name(&self) -> &str {
&self.name
}
}
#[cfg(feature = "python")]
#[allow(missing_docs)]
pub mod pybind {
use std::cell::UnsafeCell;
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};
use super::{Debug, Observer, ObserversTuple, String, Vec};
use crate::{
bolts::tuples::{type_eq, MatchName, Named},
executors::{pybind::PythonExitKind, ExitKind},
inputs::{BytesInput, HasBytesVec},
observers::map::pybind::{
PythonMapObserverI16, PythonMapObserverI32, PythonMapObserverI64, PythonMapObserverI8,
PythonMapObserverU16, PythonMapObserverU32, PythonMapObserverU64, PythonMapObserverU8,
PythonMapObserverWrapperI16, PythonMapObserverWrapperI32, PythonMapObserverWrapperI64,
PythonMapObserverWrapperI8, PythonMapObserverWrapperU16, PythonMapObserverWrapperU32,
PythonMapObserverWrapperU64, PythonMapObserverWrapperU8,
},
state::pybind::{PythonStdState, PythonStdStateWrapper},
Error,
};
#[derive(Debug)]
pub struct PyObjectObserver {
inner: PyObject,
name: UnsafeCell<String>,
}
impl Clone for PyObjectObserver {
fn clone(&self) -> PyObjectObserver {
PyObjectObserver {
inner: self.inner.clone(),
name: UnsafeCell::new(String::new()),
}
}
}
impl PyObjectObserver {
#[must_use]
pub fn new(obj: PyObject) -> Self {
PyObjectObserver {
inner: obj,
name: UnsafeCell::new(String::new()),
}
}
}
crate::impl_serde_pyobjectwrapper!(PyObjectObserver, inner);
impl Named for PyObjectObserver {
fn name(&self) -> &str {
let s = Python::with_gil(|py| -> PyResult<String> {
let s: String = self.inner.call_method0(py, "name")?.extract(py)?;
Ok(s)
})
.unwrap();
unsafe {
*self.name.get() = s;
&*self.name.get()
}
}
}
impl Observer<PythonStdState> for PyObjectObserver {
fn flush(&mut self) -> Result<(), Error> {
Python::with_gil(|py| -> PyResult<()> {
self.inner.call_method0(py, "flush")?;
Ok(())
})
.unwrap();
Ok(())
}
fn pre_exec(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
) -> Result<(), Error> {
Python::with_gil(|py| -> PyResult<()> {
self.inner.call_method1(
py,
"pre_exec",
(PythonStdStateWrapper::wrap(state), input.bytes()),
)?;
Ok(())
})?;
Ok(())
}
fn post_exec(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
Python::with_gil(|py| -> PyResult<()> {
self.inner.call_method1(
py,
"post_exec",
(
PythonStdStateWrapper::wrap(state),
input.bytes(),
PythonExitKind::from(*exit_kind),
),
)?;
Ok(())
})?;
Ok(())
}
fn pre_exec_child(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
) -> Result<(), Error> {
Python::with_gil(|py| -> PyResult<()> {
self.inner.call_method1(
py,
"pre_exec_child",
(PythonStdStateWrapper::wrap(state), input.bytes()),
)?;
Ok(())
})?;
Ok(())
}
fn post_exec_child(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
Python::with_gil(|py| -> PyResult<()> {
self.inner.call_method1(
py,
"post_exec_child",
(
PythonStdStateWrapper::wrap(state),
input.bytes(),
PythonExitKind::from(*exit_kind),
),
)?;
Ok(())
})?;
Ok(())
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum PythonObserverWrapper {
MapI8(Py<PythonMapObserverI8>),
MapI16(Py<PythonMapObserverI16>),
MapI32(Py<PythonMapObserverI32>),
MapI64(Py<PythonMapObserverI64>),
MapU8(Py<PythonMapObserverU8>),
MapU16(Py<PythonMapObserverU16>),
MapU32(Py<PythonMapObserverU32>),
MapU64(Py<PythonMapObserverU64>),
Python(PyObjectObserver),
}
#[pyclass(unsendable, name = "Observer")]
#[allow(clippy::unsafe_derive_deserialize)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PythonObserver {
pub wrapper: PythonObserverWrapper,
}
macro_rules! unwrap_me {
($wrapper:expr, $name:ident, $body:block) => {
match &$wrapper {
PythonObserverWrapper::MapI8(py_wrapper) => Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperI8,
borrowed.wrapper,
$name,
$body
))
})
.unwrap(),
PythonObserverWrapper::MapI16(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperI16,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapI32(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperI32,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapI64(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperI64,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapU8(py_wrapper) => Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperU8,
borrowed.wrapper,
$name,
$body
))
})
.unwrap(),
PythonObserverWrapper::MapU16(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperU16,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapU32(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperU32,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapU64(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let borrowed = py_wrapper.borrow(py);
Ok(crate::mapob_unwrap_me!(
PythonMapObserverWrapperU64,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::Python(py_wrapper) => {
let $name = py_wrapper;
$body
}
}
};
}
macro_rules! unwrap_me_mut {
($wrapper:expr, $name:ident, $body:block) => {
match &mut $wrapper {
PythonObserverWrapper::MapI8(py_wrapper) => Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperI8,
borrowed.wrapper,
$name,
$body
))
})
.unwrap(),
PythonObserverWrapper::MapI16(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperI16,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapI32(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperI32,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapI64(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperI64,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapU8(py_wrapper) => Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperU8,
borrowed.wrapper,
$name,
$body
))
})
.unwrap(),
PythonObserverWrapper::MapU16(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperU16,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapU32(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperU32,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::MapU64(py_wrapper) => {
Python::with_gil(|py| -> PyResult<_> {
let mut borrowed = py_wrapper.borrow_mut(py);
Ok(crate::mapob_unwrap_me_mut!(
PythonMapObserverWrapperU64,
borrowed.wrapper,
$name,
$body
))
})
.unwrap()
}
PythonObserverWrapper::Python(py_wrapper) => {
let $name = py_wrapper;
$body
}
}
};
}
#[pymethods]
impl PythonObserver {
#[staticmethod]
#[must_use]
pub fn new_map_i8(map_observer: Py<PythonMapObserverI8>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapI8(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_map_i16(map_observer: Py<PythonMapObserverI16>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapI16(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_map_i32(map_observer: Py<PythonMapObserverI32>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapI32(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_map_i64(map_observer: Py<PythonMapObserverI64>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapI64(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_map_u8(map_observer: Py<PythonMapObserverU8>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapU8(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_map_u16(map_observer: Py<PythonMapObserverU16>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapU16(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_map_u32(map_observer: Py<PythonMapObserverU32>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapU32(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_map_u64(map_observer: Py<PythonMapObserverU64>) -> Self {
Self {
wrapper: PythonObserverWrapper::MapU64(map_observer),
}
}
#[staticmethod]
#[must_use]
pub fn new_py(py_observer: PyObject) -> Self {
Self {
wrapper: PythonObserverWrapper::Python(PyObjectObserver::new(py_observer)),
}
}
pub fn unwrap_py(&self) -> Option<PyObject> {
match &self.wrapper {
PythonObserverWrapper::Python(pyo) => Some(pyo.inner.clone()),
_ => None,
}
}
}
impl Named for PythonObserver {
fn name(&self) -> &str {
let ptr = unwrap_me!(self.wrapper, o, { o.name() as *const str });
unsafe { ptr.as_ref().unwrap() }
}
}
impl Observer<PythonStdState> for PythonObserver {
fn flush(&mut self) -> Result<(), Error> {
unwrap_me_mut!(self.wrapper, o, { Observer::<PythonStdState>::flush(o) })
}
fn pre_exec(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
) -> Result<(), Error> {
unwrap_me_mut!(self.wrapper, o, { o.pre_exec(state, input) })
}
fn post_exec(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
unwrap_me_mut!(self.wrapper, o, { o.post_exec(state, input, exit_kind) })
}
fn pre_exec_child(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
) -> Result<(), Error> {
unwrap_me_mut!(self.wrapper, o, { o.pre_exec_child(state, input) })
}
fn post_exec_child(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
unwrap_me_mut!(self.wrapper, o, {
o.post_exec_child(state, input, exit_kind)
})
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[allow(clippy::unsafe_derive_deserialize)]
#[pyclass(unsendable, name = "ObserversTuple")]
pub struct PythonObserversTuple {
list: Vec<PythonObserver>,
}
#[pymethods]
impl PythonObserversTuple {
#[new]
fn new(list: Vec<PythonObserver>) -> Self {
Self { list }
}
fn len(&self) -> usize {
self.list.len()
}
fn __getitem__(&self, idx: usize) -> PythonObserver {
self.list[idx].clone()
}
#[pyo3(name = "match_name")]
fn pymatch_name(&self, name: &str) -> Option<PythonObserver> {
for ob in &self.list {
if *ob.name() == *name {
return Some(ob.clone());
}
}
None
}
}
impl ObserversTuple<PythonStdState> for PythonObserversTuple {
fn pre_exec_all(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
) -> Result<(), Error> {
for ob in &mut self.list {
ob.pre_exec(state, input)?;
}
Ok(())
}
fn post_exec_all(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
for ob in &mut self.list {
ob.post_exec(state, input, exit_kind)?;
}
Ok(())
}
fn pre_exec_child_all(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
) -> Result<(), Error> {
for ob in &mut self.list {
ob.pre_exec_child(state, input)?;
}
Ok(())
}
fn post_exec_child_all(
&mut self,
state: &mut PythonStdState,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
for ob in &mut self.list {
ob.post_exec_child(state, input, exit_kind)?;
}
Ok(())
}
#[inline]
fn observes_stdout(&self) -> bool {
false
}
#[inline]
fn observes_stderr(&self) -> bool {
false
}
#[inline]
fn observe_stderr(&mut self, _: &[u8]) {}
#[inline]
fn observe_stdout(&mut self, _: &[u8]) {}
}
impl MatchName for PythonObserversTuple {
fn match_name<T>(&self, name: &str) -> Option<&T> {
unsafe {
let mut r = None;
for ob in &self.list {
Python::with_gil(|py| -> PyResult<_> {
match &ob.wrapper {
PythonObserverWrapper::MapI8(py_wrapper) => {
if type_eq::<PythonMapObserverI8, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::MapI16(py_wrapper) => {
if type_eq::<PythonMapObserverI16, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::MapI32(py_wrapper) => {
if type_eq::<PythonMapObserverI32, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::MapI64(py_wrapper) => {
if type_eq::<PythonMapObserverI64, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::MapU8(py_wrapper) => {
if type_eq::<PythonMapObserverU8, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::MapU16(py_wrapper) => {
if type_eq::<PythonMapObserverU16, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::MapU32(py_wrapper) => {
if type_eq::<PythonMapObserverU32, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::MapU64(py_wrapper) => {
if type_eq::<PythonMapObserverU64, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow(py)) as *const T)
.as_ref();
}
}
PythonObserverWrapper::Python(py_wrapper) => {
if type_eq::<PyObjectObserver, T>() && py_wrapper.name() == name {
r = (py_wrapper as *const _ as *const T).as_ref();
}
}
}
Ok(())
})
.unwrap();
}
r
}
}
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T> {
unsafe {
let mut r = None;
for ob in &mut self.list {
Python::with_gil(|py| -> PyResult<_> {
match &mut ob.wrapper {
PythonObserverWrapper::MapI8(py_wrapper) => {
if type_eq::<PythonMapObserverI8, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::MapI16(py_wrapper) => {
if type_eq::<PythonMapObserverI16, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::MapI32(py_wrapper) => {
if type_eq::<PythonMapObserverI32, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::MapI64(py_wrapper) => {
if type_eq::<PythonMapObserverI64, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::MapU8(py_wrapper) => {
if type_eq::<PythonMapObserverU8, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::MapU16(py_wrapper) => {
if type_eq::<PythonMapObserverU16, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::MapU32(py_wrapper) => {
if type_eq::<PythonMapObserverU32, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::MapU64(py_wrapper) => {
if type_eq::<PythonMapObserverU64, T>()
&& py_wrapper.borrow(py).name() == name
{
r = (std::ptr::addr_of!(*(*py_wrapper).borrow_mut(py))
as *mut T)
.as_mut();
}
}
PythonObserverWrapper::Python(py_wrapper) => {
if type_eq::<PyObjectObserver, T>() && py_wrapper.name() == name {
r = (py_wrapper as *mut _ as *mut T).as_mut();
}
}
}
Ok(())
})
.unwrap();
}
r
}
}
}
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonObserver>()?;
m.add_class::<PythonObserversTuple>()?;
Ok(())
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod tests {
use crate::{
bolts::tuples::{tuple_list, tuple_list_type, Named},
observers::{StdMapObserver, TimeObserver},
};
static mut MAP: [u32; 4] = [0; 4];
#[test]
fn test_observer_serde() {
let obv = tuple_list!(TimeObserver::new("time"), unsafe {
StdMapObserver::new("map", &mut MAP)
});
let vec = postcard::to_allocvec(&obv).unwrap();
println!("{vec:?}");
let obv2: tuple_list_type!(TimeObserver, StdMapObserver<u32, false>) =
postcard::from_bytes(&vec).unwrap();
assert_eq!(obv.0.name(), obv2.0.name());
}
}