Skip to content

Commit

Permalink
Merge pull request #53 from asynchronics/feature/util
Browse files Browse the repository at this point in the history
Add asynchronix-util crate
  • Loading branch information
sbarral authored Oct 31, 2024
2 parents 8f70576 + 0732a7e commit 06079bd
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
members = ["asynchronix"]
members = ["asynchronix", "asynchronix-util"]
resolver = "2"
7 changes: 7 additions & 0 deletions asynchronix-util/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "asynchronix-util"
version = "0.1.0"
edition = "2021"

[dependencies]
asynchronix = {version = "0.2.2", path = "../asynchronix"}
3 changes: 3 additions & 0 deletions asynchronix-util/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Utilities for model-building

TODO: add documentation
1 change: 1 addition & 0 deletions asynchronix-util/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod observables;
90 changes: 90 additions & 0 deletions asynchronix-util/src/observables.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use std::ops::Deref;

use asynchronix::ports::Output;

/// Observability trait.
pub trait Observable<T> {
/// Observe the value.
fn observe(&self) -> T;
}

impl<T> Observable<T> for T
where
T: Clone,
{
fn observe(&self) -> Self {
self.clone()
}
}

/// Observable state.
///
/// This object encapsulates state. Every state change is propagated to the
/// output.
#[derive(Debug)]
pub struct ObservableState<S, T>
where
S: Observable<T> + Default,
T: Clone + Send + 'static,
{
/// State.
state: S,

/// Output used for observation.
out: Output<T>,
}

impl<S, T> ObservableState<S, T>
where
S: Observable<T> + Default,
T: Clone + Send + 'static,
{
/// New default state.
pub fn new(out: Output<T>) -> Self {
Self {
state: S::default(),
out,
}
}

/// Get state.
pub fn get(&self) -> &S {
&self.state
}

/// Set state.
pub async fn set(&mut self, value: S) {
self.state = value;
self.out.send(self.state.observe()).await;
}

/// Modify state using mutable reference.
pub async fn modify<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut S) -> R,
{
let r = f(&mut self.state);
self.out.send(self.state.observe()).await;
r
}

/// Propagate value.
pub async fn propagate(&mut self) {
self.out.send(self.state.observe()).await;
}
}

impl<S, T> Deref for ObservableState<S, T>
where
S: Observable<T> + Default,
T: Clone + Send + 'static,
{
type Target = S;

fn deref(&self) -> &S {
&self.state
}
}

/// Observable value.
pub type ObservableValue<T> = ObservableState<T, T>;
2 changes: 2 additions & 0 deletions asynchronix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ name = "asynchronix"
# - Update crate version in this Cargo.toml
# - Update crate version in README.md
# - Update crate version in the lib.rs documentation of feature flags
# - Update dependency in sibling crates
# - Remove path dependencies
# - Update CHANGELOG.md
# - Update if necessary copyright notice in LICENSE-MIT
# - Create a "vX.Y.Z" git tag
Expand Down

0 comments on commit 06079bd

Please sign in to comment.