Skip to content

Commit

Permalink
feat!: add side effect state transformers (#35)
Browse files Browse the repository at this point in the history
Fixes #30
  • Loading branch information
GregoryConrad authored Jan 16, 2024
1 parent f20f626 commit 0f8e864
Show file tree
Hide file tree
Showing 9 changed files with 459 additions and 190 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ readme = "README.md"
[workspace.dependencies]
rearch-macros = { path = "rearch-macros", version = "0.6.0" }
rearch = { path = "rearch", version = "0.9.1" }
rearch-effects = { path = "rearch-effects", version = "0.3.0" }
rearch-effects = { path = "rearch-effects", version = "0.3.0", default-features = false }
rearch-tokio = { path = "rearch-tokio", version = "0.8.0" }

[workspace.lints.rust]
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Define your "capsules" (en-_capsulated_ pieces of state) at the top level:

// This capsule provides the count and a way to increment that count.
fn count_manager(CapsuleHandle { register, .. }: CapsuleHandle) -> (u8, impl CData + Fn()) {
let (count, set_count) = register(effects::cloneable::state(0));
let (count, set_count) = register(effects::state::<Cloned<_>>(0));
let increment_count = move || set_count(count + 1);
(count, increment_count)
}
Expand Down Expand Up @@ -87,7 +87,8 @@ Also, there is some WIP [documentation] that will help you learn the core concep


## Minimum Supported Rust Version (MSRV)
The MSRV is currently 1.74.0 and may change in any new ReArch version/release.
The MSRV of `rearch` is currently 1.74.0 and may change in any new ReArch version/release.
The MSRV of other crates in this repo will be the latest stable release for the foreseeable future.

It is also worth mentioning that the example shown in "In a Nutshell" above requires nightly
for `unboxed_closures` and `fn_traits`, which is feature-gated under the `experimental-api` feature.
Expand Down
4 changes: 2 additions & 2 deletions examples/simple-demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use effects::Cloned;
use rearch::{CData, CapsuleHandle, Container};
use rearch_effects as effects;

Expand Down Expand Up @@ -29,8 +30,7 @@ fn uses_factory_capsule(CapsuleHandle { mut get, .. }: CapsuleHandle) -> String
}

fn stateful_capsule(CapsuleHandle { register, .. }: CapsuleHandle) -> (u32, impl CData + Fn(u32)) {
let (state, set_state) = register.register(effects::state(0));
(*state, set_state)
register.register(effects::state::<Cloned<_>>(0))
}

fn main() {
Expand Down
8 changes: 7 additions & 1 deletion rearch-effects/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@ readme.workspace = true
workspace = true

[dependencies]
once_cell = { version = "1.19.0", default-features = false}
once_cell = { version = "1.19.0", default-features = false, optional = true}
rearch = { workspace = true }

[features]
default = ["lazy-state-transformers"]

# Enable the lazy state transformers via once_cell::unsync::Lazy
lazy-state-transformers = ["dep:once_cell"]
33 changes: 0 additions & 33 deletions rearch-effects/src/cloneable.rs

This file was deleted.

71 changes: 71 additions & 0 deletions rearch-effects/src/effect_lifetime_fixers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::StateTransformer;
use rearch::{SideEffect, SideEffectRegistrar};

// These workarounds were derived from:
// https://github.com/GregoryConrad/rearch-rs/issues/3#issuecomment-1872869363
// And are needed because of:
// https://github.com/rust-lang/rust/issues/111662
// A big thank you to https://github.com/0e4ef622 for all of their help here!

pub struct EffectLifetimeFixer0<F, ST>(F, std::marker::PhantomData<ST>);
impl<F, ST> SideEffect for EffectLifetimeFixer0<F, ST>
where
F: FnOnce(SideEffectRegistrar) -> ST::Output<'_>,
ST: StateTransformer,
{
type Api<'a> = ST::Output<'a>;
fn build(self, registrar: SideEffectRegistrar) -> Self::Api<'_> {
self.0(registrar)
}
}
impl<F, ST> EffectLifetimeFixer0<F, ST> {
pub(super) const fn new(f: F) -> Self
where
F: FnOnce(SideEffectRegistrar) -> ST::Output<'_>,
ST: StateTransformer,
{
Self(f, std::marker::PhantomData)
}
}

pub struct EffectLifetimeFixer1<F, ST>(F, std::marker::PhantomData<ST>);
impl<F, ST, R1> SideEffect for EffectLifetimeFixer1<F, ST>
where
F: FnOnce(SideEffectRegistrar) -> (ST::Output<'_>, R1),
ST: StateTransformer,
{
type Api<'a> = (ST::Output<'a>, R1);
fn build(self, registrar: SideEffectRegistrar) -> Self::Api<'_> {
self.0(registrar)
}
}
impl<F, ST> EffectLifetimeFixer1<F, ST> {
pub(super) const fn new<R1>(f: F) -> Self
where
F: FnOnce(SideEffectRegistrar) -> (ST::Output<'_>, R1),
ST: StateTransformer,
{
Self(f, std::marker::PhantomData)
}
}

pub struct EffectLifetimeFixer2<F, ST>(F, std::marker::PhantomData<ST>);
impl<F, ST, R1, R2> SideEffect for EffectLifetimeFixer2<F, ST>
where
F: FnOnce(SideEffectRegistrar) -> (ST::Output<'_>, R1, R2),
ST: StateTransformer,
{
type Api<'a> = (ST::Output<'a>, R1, R2);
fn build(self, registrar: SideEffectRegistrar) -> Self::Api<'_> {
self.0(registrar)
}
}
impl<F, ST> EffectLifetimeFixer2<F, ST> {
pub(super) const fn new<R1, R2>(f: F) -> Self
where
F: FnOnce(SideEffectRegistrar) -> (ST::Output<'_>, R1, R2),
ST: StateTransformer,
{
Self(f, std::marker::PhantomData)
}
}
Loading

0 comments on commit 0f8e864

Please sign in to comment.