FromListener

Trait FromListener 

Source
pub trait FromListener<L: Listener<M>, M>: Listener<M> {
    // Required method
    fn from_listener(listener: L) -> Self;
}
Expand description

Conversion from a specific listener type to a more general listener type, such as a trait object.

This trait is typically used via calling Listen::listen(), or an IntoListener bound on a function’s parameter, to convert listeners of the provided type into a more common type that can be stored in a Notifier’s listener set.

§Generic parameters

  • Self is the listener type being converted to.
  • L is the listener type being converted from.
  • M is the type of message accepted by the listener.

§When to implement FromListener

There are two kinds of implementations of FromListener:

  • Conversion to trait objects, like sync::DynListener and unsync::DynListener, or enums. You would write such an implementation if you are using a custom type for your type-erased listeners (e.g. to add more required traits to allow more inspection of the listeners).

  • Reflexive implementations, allowing the use of a Notifier that accepts only one type of listener and does no dynamic dispatch. You may write such an implementation, impl FromListener<MyListener, MyMsg> for MyListener, whenever you implement Listener.

    Unfortunately, we cannot provide a blanket implementation of this type, impl<L: Listener<M>, M> FromListener<L, M> for L, because it would conflict with the other kind of implementation.

§Example implementation

Suppose that you want to use only Flag and WakeFlag listeners, perhaps because they use atomic operations and no custom code or locks. A custom implementation of FromListener can offer this restriction, and potential performance improvement by avoiding indirection and allocation:

use nosy::Listen as _;

/// A non-boxing type for all `Flag` listeners and no other kinds of listener.
#[derive(Debug)]
enum AnyFlag {
    NoWake(nosy::FlagListener),
    Wake(nosy::future::WakeFlagListener),
}

// Dispatches to the listeners in each variant.
impl<M> nosy::Listener<M> for AnyFlag {
    fn receive(&self, messages: &[M]) -> bool {
       match self {
           Self::NoWake(l) => l.receive(messages),
           Self::Wake(l) => l.receive(messages),
       }
    }
}

// Whenever possible, provide a reflexive, idempotent implementation,
// so that an already-converted listener can still be passed to `listen()` methods.
impl<M> nosy::FromListener<AnyFlag, M> for AnyFlag {
    fn from_listener(listener: AnyFlag) -> AnyFlag {
        listener
    }
}

// The actual work of conversion.
impl<M> nosy::FromListener<nosy::FlagListener, M> for AnyFlag {
    fn from_listener(listener: nosy::FlagListener) -> AnyFlag {
        AnyFlag::NoWake(listener)
    }
}
impl<M> nosy::FromListener<nosy::future::WakeFlagListener, M> for AnyFlag {
    fn from_listener(listener: nosy::future::WakeFlagListener) -> AnyFlag {
        AnyFlag::Wake(listener)
    }
}

fn example_usage(notifier: &nosy::Notifier<(), AnyFlag>) {
    notifier.listen(nosy::Flag::new(false).listener());
}

§Why not From?

The reason we define this trait instead of using the standard From trait is that coherence would prohibit providing the needed blanket implementations — we cannot write

impl<L, M> From<L> for nosy::unsync::DynListener<M>
where
    L: nosy::Listener<M>,

because L is an uncovered type parameter and DynListener is not a local type, and even if that were not the case, this implementation would conflict with the blanket implementation impl<T> From<T> for T.

Required Methods§

Source

fn from_listener(listener: L) -> Self

Convert the given Listener into Self.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<L, M> FromListener<L, M> for nosy::sync::DynListener<M>
where L: Listener<M> + Send + Sync + 'static,

Source§

impl<L, M> FromListener<L, M> for nosy::unsync::DynListener<M>
where L: Listener<M> + 'static,

Source§

impl<L: Listener<M>, M> FromListener<GateListener<L>, M> for GateListener<L>

Source§

impl<L: Listener<M>, M> FromListener<NotifierForwarder<M, L>, M> for NotifierForwarder<M, L>

Source§

impl<M> FromListener<WakeFlagListener, M> for WakeFlagListener

Source§

impl<M> FromListener<FlagListener, M> for FlagListener

Source§

impl<M> FromListener<NullListener, M> for NullListener

Source§

impl<M: Clone + Send + Sync> FromListener<LogListener<M>, M> for LogListener<M>

Source§

impl<MI, MO, F, T, const BATCH: usize> FromListener<Filter<F, T, BATCH>, MI> for Filter<F, T, BATCH>
where F: Fn(&MI) -> Option<MO> + Send + Sync, T: Listener<MO>,

Source§

impl<T: ?Sized + Store<M> + Send, M> FromListener<StoreLockListener<T>, M> for StoreLockListener<T>