use std::fmt::Debug;
use std::sync::Arc;
pub trait Sink<T> {
fn send(&self, item: T);
}
impl<T, S: ?Sized> Sink<T> for &S
where
S: Sink<T>,
{
fn send(&self, item: T) {
Sink::send(*self, item)
}
}
pub trait SinkMut<T> {
fn send(&mut self, item: T);
}
impl<T, S: ?Sized> SinkMut<T> for &mut S
where
S: SinkMut<T>,
{
fn send(&mut self, item: T) {
SinkMut::send(*self, item)
}
}
impl<T, S: ?Sized> SinkMut<T> for &S
where
S: Sink<T>,
{
fn send(&mut self, item: T) {
Sink::send(*self, item)
}
}
pub trait SinkOnce<T> {
fn send(self, item: T);
}
impl<T, S: ?Sized> SinkOnce<T> for &S
where
S: Sink<T>,
{
fn send(self, item: T) {
Sink::send(&self, item)
}
}
impl<T, S: ?Sized> SinkOnce<T> for &mut S
where
S: SinkMut<T>,
{
fn send(mut self, item: T) {
SinkMut::send(&mut self, item)
}
}
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub struct LogTarget(&'static str);
impl From<&'static str> for LogTarget {
fn from(target: &'static str) -> Self {
Self(target)
}
}
impl From<LogTarget> for &'static str {
fn from(target: LogTarget) -> Self {
target.0
}
}
pub trait Logger<T>: Send + Sync {
fn log(&self, ev: T);
fn filter<P>(self, predicate: P) -> Filter<P, Self>
where
Self: Sized,
P: Send + Sync + Fn(&T) -> bool,
{
Filter::new(self, predicate)
}
fn map<S, F>(self, f: F) -> Map<F, Self>
where
Self: Sized,
F: Send + Sync + Fn(S) -> T,
{
Map::new(self, f)
}
fn filter_map<S, F>(self, f: F) -> FilterMap<F, Self>
where
Self: Sized,
F: Send + Sync + Fn(S) -> Option<T>,
{
FilterMap::new(self, f)
}
}
pub struct Filter<P, L> {
logger: L,
predicate: P,
}
impl<P, L> Filter<P, L> {
fn new(logger: L, predicate: P) -> Self {
Self { logger, predicate }
}
}
impl<T, P, L> Logger<T> for Filter<P, L>
where
P: Send + Sync + Fn(&T) -> bool,
L: Logger<T>,
{
fn log(&self, ev: T) {
if (self.predicate)(&ev) {
self.logger.log(ev);
}
}
}
pub struct Map<F, L> {
logger: L,
f: F,
}
impl<F, L> Map<F, L> {
fn new(logger: L, f: F) -> Self {
Self { logger, f }
}
}
impl<T, U, F, L> Logger<T> for Map<F, L>
where
F: Send + Sync + Fn(T) -> U,
L: Logger<U>,
{
fn log(&self, ev: T) {
self.logger.log((self.f)(ev))
}
}
pub struct FilterMap<F, L> {
logger: L,
f: F,
}
impl<F, L> FilterMap<F, L> {
fn new(logger: L, f: F) -> Self {
Self { logger, f }
}
}
impl<T, U, F, L> Logger<T> for FilterMap<F, L>
where
F: Send + Sync + Fn(T) -> Option<U>,
L: Logger<U>,
{
fn log(&self, ev: T) {
if let Some(ev) = (self.f)(ev) {
self.logger.log(ev)
}
}
}
impl<L, Ev> Logger<Ev> for &L
where
L: ?Sized + Logger<Ev>,
{
fn log(&self, ev: Ev) {
Logger::log(*self, ev)
}
}
impl<L, Ev> Logger<Ev> for Arc<L>
where
L: ?Sized + Logger<Ev>,
{
fn log(&self, ev: Ev) {
Logger::log(self.as_ref(), ev)
}
}
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
pub struct NoopLogger;
impl<Ev> Logger<Ev> for NoopLogger {
fn log(&self, _ev: Ev) {}
}
pub struct StderrLogger;
impl<Ev> Logger<Ev> for StderrLogger
where
Ev: Debug,
{
fn log(&self, ev: Ev) {
eprintln!("{:?}", ev);
}
}
impl<T> SinkMut<T> for Vec<T> {
fn send(&mut self, item: T) {
self.push(item);
}
}
impl<T> SinkMut<T> for Option<T> {
fn send(&mut self, item: T) {
*self = Some(item);
}
}