crier 0.3.2

A simple but flexible observer library
Documentation
  • Coverage
  • 42.11%
    8 out of 19 items documented1 out of 1 items with examples
  • Size
  • Source code size: 22.67 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 2.16 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 22s Average build duration of successful builds.
  • all releases: 17s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • hollg

crier

crier is a simple but flexible observer library for Rust.

Goals

Simplicity

crier has a simple API using basic Rust types. The complex types needed to make it work are all abstracted away from the consumer.

Flexibility

  • A crier Publisher can handle any number of different types of events and handlers.
  • You can create a handler by wrapping a simple closure in crier's Handler struct, or you can implement the Handle trait manually on your own types. You can even do both for different handlers subscribed to the same Publisher.

Usage

Subscribe a simple closure

use crier::{Event, Handler, Publisher};

#[derive(Clone, Event)]
struct Warning(String);

#[derive(Clone, Event)]
struct Info(String);

fn main() {
    let mut publisher = Publisher::default();
    let warning_handler = Handler::new(|warning: Warning| println!("Warning: {}", warning.0));
    let warning_id = publisher.subscribe(warning_handler);

    // `publish` returns a Result, the error variant of which contains any errors returned by triggered handlers
    let _ = publisher.publish(Warning(String::from("Looks sus")));

    // This event will not trigger the warning_handler because it's of the wrong concrete type
    let _ = publisher.publish(Info(String::from("All good")));

    publisher.unsubscribe(warning_id);
}

Subscribe a custom type with a mut handler function

use crier::{Event, Publisher, HandleMut};

#[derive(Clone, Event)]
struct Info(String);

#[derive(Default)]
struct InfoHandler {
    count: usize;
}

impl HandleMut for InfoHandler {
    type EventType = Info;

    fn handle_mut(&mut self, event: Self::EventType) {
        self.count += 1;
        println!("Info: {}", event.0)
        println!("Triggered {} times", self.count);
    }
}

fn main() {
    let mut publisher = Publisher::default();
    let info_handler = InfoHandler::default();
    let info_id = publisher.subscribe_mut(info_handler);

    let _ = publisher.publish(Info(String::from("All good"))); 

    publisher.unsubscribe_mut(info_id);
}

Check out the examples directory for more!

TODO:

  • Publisher supports any number of handlers / events of different types
  • Derive macro for Event trait
  • Optional async feature using Tokio
  • Support handlers that take a mut &self receiver when implementing Handle for custom types to enable more complex use cases, e.g. updating some internal state when events are received

Acknowledgements

Thanks to @klaatu01 for giving me the idea to build this and the coaching I needed to wrangle Rust's type system into allowing events and handlers of multiple different types in a single publisher.