use std::marker::PhantomData;
#[cfg(feature="cons_mode")]
use std::sync::Arc;
#[cfg(feature="cons_mode")]
use std::slice;
#[cfg(feature="cons_mode")]
use std::mem;
#[cfg(feature="cons_mode")]
use std::ptr;
#[cfg(feature="cons_mode")]
use libc::*;
use crate::simulation;
use crate::simulation::point::Point;
#[cfg(feature="cons_mode")]
use crate::simulation::error::*;
#[cfg(feature="cons_mode")]
use crate::simulation::utils::byte_vec::*;
#[inline]
pub fn return_observer<M, T>(val: T) -> Return<M, T>
where T: Clone
{
Return { val: val, _phantom: PhantomData }
}
#[inline]
pub fn delay_observer<F, O>(f: F) -> Delay<F, O>
where F: Fn() -> O,
O: Observer
{
Delay { f: f, _phantom: PhantomData }
}
#[inline]
pub fn cons_observer<F, M, T>(f: F) -> Cons<F, M, T>
where F: Fn(&M, &Point) -> simulation::Result<T>
{
Cons { f: f, _phantom1: PhantomData, _phantom2: PhantomData }
}
#[inline]
pub fn message_observer<M>() -> Message<M>
where M: Clone
{
Message { _phantom: PhantomData }
}
#[inline]
pub fn trace_observer<O>(msg: String, comp: O) -> Trace<O>
where O: Observer
{
Trace { comp: comp, msg: msg}
}
pub trait Observer {
type Message;
type Item;
#[doc(hidden)]
fn call_observer(&self, m: &Self::Message, p: &Point) -> simulation::Result<Self::Item>;
#[inline]
fn and_then<U, F>(self, f: F) -> AndThen<Self, U, F>
where Self: Sized,
U: Observer<Message = Self::Message>,
F: Fn(Self::Item) -> U,
{
AndThen { comp: self, f: f, _phantom: PhantomData }
}
#[inline]
fn map<B, F>(self, f: F) -> Map<Self, B, F>
where Self: Sized,
F: Fn(Self::Item) -> B,
{
Map { comp: self, f: f, _phantom: PhantomData }
}
#[inline]
fn zip<U>(self, other: U) -> Zip<Self, U>
where Self: Sized,
U: Observer<Message = Self::Message>
{
Zip { comp: self, other: other }
}
#[inline]
fn ap<U, B>(self, other: U) -> Ap<Self, U, B>
where Self: Sized,
Self::Item: Fn(U::Item) -> B,
U: Observer<Message = Self::Message>
{
Ap { comp: self, other: other, _phantom: PhantomData }
}
#[inline]
fn into_boxed(self) -> ObserverBox<Self::Message, Self::Item>
where Self: Sized + 'static
{
ObserverBox::new(move |m: &Self::Message, p: &Point| {
self.call_observer(m, p)
})
}
}
pub trait IntoObserver {
type Observer: Observer<Message = Self::Message, Item = Self::Item>;
type Message;
type Item;
fn into_observer(self) -> Self::Observer;
}
impl<M: Observer> IntoObserver for M {
type Observer = M;
type Message = M::Message;
type Item = M::Item;
#[inline]
fn into_observer(self) -> Self::Observer {
self
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct ObserverBox<M, T> {
f: Box<dyn Fn(&M, &Point) -> simulation::Result<T>>
}
impl<M, T> ObserverBox<M, T> {
#[doc(hidden)]
#[inline]
fn new<F>(f: F) -> Self
where F: Fn(&M, &Point) -> simulation::Result<T> + 'static
{
ObserverBox {
f: Box::new(f)
}
}
#[doc(hidden)]
#[inline]
pub fn call(&self, m: &M, p: &Point) -> simulation::Result<T> {
let ObserverBox { f } = self;
f(m, p)
}
}
impl<M, T> Observer for ObserverBox<M, T> {
type Message = M;
type Item = T;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &M, p: &Point) -> simulation::Result<T> {
self.call(m, p)
}
#[inline]
fn into_boxed(self) -> ObserverBox<Self::Message, Self::Item>
where Self: Sized + 'static
{
self
}
}
#[cfg(feature="cons_mode")]
#[repr(C)]
#[derive(Copy, Clone)]
struct ObserverTraitObject {
field1: *mut c_void,
field2: *mut c_void
}
#[cfg(feature="cons_mode")]
#[repr(C)]
pub struct ObserverRepr {
delete: unsafe extern "C" fn(obj: *mut ObserverTraitObject),
callback: unsafe extern "C" fn(obj: *const ObserverTraitObject, message: *const u8, count: usize, p: *const Point) -> *mut ErrorRepr,
trait_object: ObserverTraitObject
}
#[cfg(feature="cons_mode")]
impl Drop for ObserverRepr {
fn drop(&mut self) {
unsafe {
(self.delete)(&mut self.trait_object);
}
}
}
#[cfg(feature="cons_mode")]
impl ObserverRepr {
#[inline]
pub fn into_repr(comp: ObserverBox<&[u8], ()>) -> ObserverRepr {
unsafe {
ObserverRepr {
delete: delete_observer_repr,
callback: call_observer_repr,
trait_object: mem::transmute(comp)
}
}
}
#[inline]
fn call_repr(&self, m: &[u8], p: &Point) -> *mut ErrorRepr {
unsafe {
(self.callback)(&self.trait_object, m.as_ptr(), m.len(), p)
}
}
}
#[cfg(feature="cons_mode")]
unsafe extern "C" fn call_observer_repr(comp: *const ObserverTraitObject, m: *const u8, count: usize, p: *const Point) -> *mut ErrorRepr {
let comp: ObserverBox<&[u8], ()> = mem::transmute(*comp);
let m = slice::from_raw_parts(m, count);
match comp.call_observer(&m, &*p) {
Result::Ok(()) => {
mem::forget(comp);
ptr::null_mut()
},
Result::Err(e) => {
mem::forget(comp);
let e = ErrorRepr::new(e);
Box::into_raw(Box::new(e))
}
}
}
#[cfg(feature="cons_mode")]
unsafe extern "C" fn delete_observer_repr(comp: *mut ObserverTraitObject) {
let _: ObserverBox<&[u8], ()> = mem::transmute(*comp);
}
#[cfg(feature="cons_mode")]
impl Observer for ObserverRepr {
type Message = Arc<ByteVecRepr>;
type Item = ();
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &Self::Message, p: &Point) -> simulation::Result<Self::Item> {
unsafe {
let m = m.slice();
let e = self.call_repr(m, p);
if e == ptr::null_mut() {
Result::Ok(())
} else {
let e = ffi_error_repr_into_error(e);
Result::Err(e)
}
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Return<M, T> {
val: T,
_phantom: PhantomData<M>
}
impl<M, T> Observer for Return<M, T>
where T: Clone
{
type Message = M;
type Item = T;
#[doc(hidden)]
#[inline]
fn call_observer(&self, _: &M, _: &Point) -> simulation::Result<T> {
Result::Ok(self.val.clone())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Delay<F, O> {
f: F,
_phantom: PhantomData<O>
}
impl<F, O> Observer for Delay<F, O>
where F: Fn() -> O,
O: Observer
{
type Message = O::Message;
type Item = O::Item;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &O::Message, p: &Point) -> simulation::Result<O::Item> {
let Delay { f, _phantom } = self;
f().call_observer(m, p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Cons<F, M, T> {
f: F,
_phantom1: PhantomData<M>,
_phantom2: PhantomData<T>
}
impl<F, M, T> Observer for Cons<F, M, T>
where F: Fn(&M, &Point) -> simulation::Result<T>
{
type Message = M;
type Item = T;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &M, p: &Point) -> simulation::Result<T> {
let Cons { f, _phantom1, _phantom2 } = self;
f(m, p)
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Message<M> {
_phantom: PhantomData<M>
}
impl<M> Observer for Message<M>
where M: Clone
{
type Message = M;
type Item = M;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &Self::Message, _: &Point) -> simulation::Result<Self::Item> {
Result::Ok(m.clone())
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct AndThen<O, U, F> {
comp: O,
f: F,
_phantom: PhantomData<U>
}
impl<O, U, F> Observer for AndThen<O, U, F>
where O: Observer,
U: Observer<Message = O::Message>,
F: Fn(O::Item) -> U,
{
type Message = U::Message;
type Item = U::Item;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &Self::Message, p: &Point) -> simulation::Result<Self::Item> {
let AndThen { comp, f, _phantom } = self;
match comp.call_observer(m, p) {
Result::Ok(a) => {
let u = f(a);
u.call_observer(m, p)
},
Result::Err(e) => {
Result::Err(e)
}
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Map<O, B, F> {
comp: O,
f: F,
_phantom: PhantomData<B>
}
impl<O, B, F> Observer for Map<O, B, F>
where O: Observer,
F: Fn(O::Item) -> B,
{
type Message = O::Message;
type Item = B;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &Self::Message, p: &Point) -> simulation::Result<Self::Item> {
let Map { comp, f, _phantom } = self;
match comp.call_observer(m, p) {
Result::Ok(a) => Result::Ok(f(a)),
Result::Err(e) => Result::Err(e)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Zip<O, U> {
comp: O,
other: U,
}
impl<O, U> Observer for Zip<O, U>
where O: Observer,
U: Observer<Message = O::Message>
{
type Message = O::Message;
type Item = (O::Item, U::Item);
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &Self::Message, p: &Point) -> simulation::Result<Self::Item> {
let Zip { comp, other } = self;
match comp.call_observer(m, p) {
Result::Ok(a) => {
match other.call_observer(m, p) {
Result::Ok(b) => Result::Ok((a, b)),
Result::Err(e) => Result::Err(e)
}
},
Result::Err(e) => Result::Err(e)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Ap<O, U, B> {
comp: O,
other: U,
_phantom: PhantomData<B>
}
impl<O, U, B> Observer for Ap<O, U, B>
where O: Observer,
U: Observer<Message = O::Message>,
O::Item: Fn(U::Item) -> B,
{
type Message = O::Message;
type Item = B;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &Self::Message, p: &Point) -> simulation::Result<Self::Item> {
let Ap { comp, other, _phantom } = self;
match comp.call_observer(m, p) {
Result::Ok(f) => {
match other.call_observer(m, p) {
Result::Ok(a) => Result::Ok(f(a)),
Result::Err(e) => Result::Err(e)
}
},
Result::Err(e) => Result::Err(e)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
#[derive(Clone)]
pub struct Trace<O> {
comp: O,
msg: String
}
impl<O> Observer for Trace<O>
where O: Observer
{
type Message = O::Message;
type Item = O::Item;
#[doc(hidden)]
#[inline]
fn call_observer(&self, m: &Self::Message, p: &Point) -> simulation::Result<Self::Item> {
let Trace { comp, msg } = self;
p.trace(&msg);
comp.call_observer(m, p)
}
}