Skip to content

Commit

Permalink
fix: improve documentation and add README
Browse files Browse the repository at this point in the history
  • Loading branch information
mhatzl committed Sep 14, 2023
1 parent ec25303 commit eba0582
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Tests
name: build-test

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "evident"
version = "0.12.0"
version = "0.12.1"
edition = "2021"
description = "Pub/Sub library using IDs to identify events."
repository = "https://github.com/mhatzl/evident"
Expand Down
63 changes: 62 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,64 @@
# evident

WIP events.
![build-test](https://github.com/mhatzl/evident/actions/workflows/rust.yml/badge.svg?branch=main)
![mantra-sync](https://github.com/mhatzl/evident/actions/workflows/mantra_sync.yml/badge.svg?branch=main)
[![crates.io](https://img.shields.io/crates/v/evident)](https://crates.io/crates/evident)

This crate makes it easy to create custom multithreaded pub/sub functionality for Rust applications.
It uses **events** to send information between publisher and subscriber, and **IDs** are used to subscribe and identify these **events** (hence *ev**ID**ent*).

The pub/sub communication is done over a central static *publisher* that captures set events,
and forwards them to subscribers. To allow using *evident* in different scenarios,
a publisher must be created per scenario, and cannot be provided by *evident* itself.
See the [setup](#setup) section below on how to create your custom pub/sub instance.

## Setup

**To customize *evident* to fit your use case, you need to implement the following traits:**

- [`Id`](https://docs.rs/evident/latest/evident/event/trait.Id.html) ... Defines the structure of the ID that is used to identify events
- [`EventEntry`](https://docs.rs/evident/latest/evident/event/entry/trait.EventEntry.html) ... Allows adding additional information to an event
- [`IntermediaryEvent`](https://docs.rs/evident/latest/evident/event/intermediary/trait.IntermediaryEvent.html) ... Allows automatic capturing of events once they go out of scope

**Optional traits to further customize *evident*:**

- [`Filter`](https://docs.rs/evident/latest/evident/event/filter/trait.Filter.html) ... To prevent capturing events
- [`Msg`](https://docs.rs/evident/latest/evident/event/trait.Msg.html) ... Allows creating a custom message to be sent with an event

**Creating your pub/sub instance:**

- [`create_static_publisher!()`](https://docs.rs/evident/latest/evident/macro.create_static_publisher.html) ... Convenience macro to create your custom [`EvidentPublisher`](https://docs.rs/evident/latest/evident/publisher/struct.EvidentPublisher.html)
- [`create_set_event_macro!()`](https://docs.rs/evident/latest/evident/macro.create_set_event_macro.html) ... Convenience macro to create the `set_event!()` macro that may be used to set your custom events

**Examples:**

- [/tests/min_concretise](https://github.com/mhatzl/evident/tree/main/tests/min_concretise) ... Contains a minimal pub/sub setup
- [/tests/min_filter](https://github.com/mhatzl/evident/tree/main/tests/min_filter) ... Contains a minimal pub/sub setup using a custom filter
- [/tests/min_msg](https://github.com/mhatzl/evident/tree/main/tests/min_msg) ... Contains a minimal pub/sub setup with a custom message

## Usage

After creating your own publisher, you can set events using the `set_event!()` macro.

**Example:**

```rust
let some_id = MinId { id: 3 };
let msg = "Some msg";

let sub = PUBLISHER.subscribe(some_id).unwrap();

set_event!(some_id, msg).finalize();

let event = sub
.get_receiver()
.recv_timeout(std::time::Duration::from_millis(100))
.unwrap();
```

**Note:** `finalize()` is set explicitly to ensure the event is sent before the subscription tries to receive it.
Otherwise, it would be sent once the event gets out of scope (is dropped).

# License

MIT Licensed
4 changes: 4 additions & 0 deletions src/event/filter.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//! Contains the [`Filter`] trait.

use std::marker::PhantomData;

use crate::publisher::CaptureControl;

use super::{entry::EventEntry, Id, Msg};

/// The [`Filter`] trait allows to add a custom filter to an [`EvidentPublisher`].
pub trait Filter<K, M>
where
K: Id + CaptureControl,
Expand All @@ -13,6 +16,7 @@ where
fn allow_entry(&self, entry: &impl EventEntry<K, M>) -> bool;
}

/// Struct used to provide a dummy filter in case no custom filter is set.
#[derive(Default, Debug)]
pub struct DummyFilter<K, M>
where
Expand Down
11 changes: 11 additions & 0 deletions src/event/finalized.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
//! Contains the [`FinalizedEvent`] struct.

use super::Id;

/// The [`FinalizedEvent`] is returned once a event is captured using [`finalize()`](super::IntermediaryEvent::finalize).
/// It stores only the event and entry IDs to prevent unnecessarry resource cloning.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct FinalizedEvent<K: Id> {
/// The [`Id`] of the associated [`Event`](super::Event).
pub event_id: K,

/// The ID of the associated [`EventEntry`](super::entry::EventEntry).
pub entry_id: crate::uuid::Uuid,
}

impl<K: Id> FinalizedEvent<K> {
/// Creates a new [`FinalizedEvent`].
pub fn new(event_id: K, entry_id: crate::uuid::Uuid) -> Self {
FinalizedEvent { event_id, entry_id }
}

/// Converts this [`FinalizedEvent`] into the associated event [`Id`].
pub fn into_event_id(self) -> K {
self.event_id
}

/// Returns the associated event [`Id].
pub fn get_event_id(&self) -> &K {
&self.event_id
}

/// Returns the associated [`EventEntry`](super::entry::EventEntry) ID.
pub fn get_entry_id(&self) -> &crate::uuid::Uuid {
&self.entry_id
}
Expand Down
14 changes: 14 additions & 0 deletions src/event/intermediary.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
//! Contains the [`IntermediaryEvent`] trait.

use super::{entry::EventEntry, finalized::FinalizedEvent, origin::Origin, Id, Msg};

/// The [`IntermediaryEvent`] trait is used to add information after setting an event,
/// and to be able to automatically capture events once they go out of scope.
pub trait IntermediaryEvent<K, M, T>
where
Self: std::marker::Sized,
K: Id,
M: Msg,
T: EventEntry<K, M>,
{
/// Create a new [`IntermediaryEvent`].
///
/// # Arguments
///
/// * `event_id` ... The [`Id`] of the event
/// * `msg` ... An optional [`Msg`] set for this event
/// * `origin` ... The [`Origin`] this event was set
fn new(event_id: K, msg: Option<impl Into<M>>, origin: Origin) -> Self;

/// Returns the [`EventEntry`] that was created by this [`IntermediaryEvent`].
fn get_entry(&self) -> &T;

/// Takes the [`EventEntry`] that was created by this [`IntermediaryEvent`].
fn take_entry(&mut self) -> T;

/// Returns the [`Id`] of this event
Expand All @@ -34,6 +47,7 @@ where
captured_event
}

/// Converts this [`IntermediaryEvent`] into the related event [`Id`].
fn into_event_id(self) -> K {
self.finalize().into_event_id()
}
Expand Down
13 changes: 13 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
//! *evident* makes it easy to create custom multithreaded pub/sub functionality.
//! Communication is achieved by capturing **events** with distinct **IDs**,
//! and forwarding those events to subscribers of the related IDs.
//!
//! The [tests/min_concretise](https://github.com/mhatzl/evident/tree/main/tests/min_concretise) folder
//! contains a minimal example on how to create your custom pub/sub setup.
//!
//! A custom filter is added in the [tests/min_filter](https://github.com/mhatzl/evident/tree/main/tests/min_filter) folder.
//! This filter may be used to prevent events from being captured.
//!
//! Checkout the [tests/min_msg](https://github.com/mhatzl/evident/tree/main/tests/min_msg) folder
//! if you want to send custom event messages instead of regular [`String`]s.

pub mod creation_macros;
pub mod event;
pub mod publisher;
Expand Down
11 changes: 11 additions & 0 deletions src/publisher.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! Contains the [`EvidentPublisher`] struct that is used to create public static publishers.
//!
//! Use the [`create_static_publisher`](crate::create_static_publisher) macro for a convenience wrapper to create a publisher.
//!
//! [req:pub]

use std::{
collections::{HashMap, HashSet},
sync::{
Expand Down Expand Up @@ -58,9 +64,14 @@ pub fn is_control_id(id: &impl CaptureControl) -> bool {
CaptureControl::stop(id) || CaptureControl::start(id)
}

/// Defines the capture mode for a publisher.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CaptureMode {
/// Event capturing may be blocking if the capture buffer is full.
Blocking,
/// Event capturing does not block, resulting in events **not** being captured if the capture buffer is full.
///
/// You may inspect the number of missed events with the `get_missed_captures()` of the [`EvidentPublisher`].
NonBlocking,
}

Expand Down
4 changes: 4 additions & 0 deletions src/subscription.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! Contains the [`Subscription`] struct that is returned by `subscribe` functions from an [`EvidentPublisher`].
//!
//! [req:subs]

use std::{
collections::{HashMap, HashSet},
hash::Hash,
Expand Down

0 comments on commit eba0582

Please sign in to comment.