use std::marker::PhantomData;
pub trait StateLens<Outer, Inner>: Send + Sync {
fn get<'a>(&self, outer: &'a mut Outer) -> &'a mut Inner;
}
pub struct IdentityLens<S> {
_phantom: PhantomData<S>,
}
impl<S> IdentityLens<S> {
pub fn new() -> Self {
Self {
_phantom: PhantomData,
}
}
}
impl<S> Default for IdentityLens<S> {
fn default() -> Self {
Self::new()
}
}
impl<S: Send + Sync> StateLens<S, S> for IdentityLens<S> {
fn get<'a>(&self, outer: &'a mut S) -> &'a mut S {
outer
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, PartialEq)]
struct OuterState {
inner: InnerState,
other: String,
}
#[derive(Debug, PartialEq)]
struct InnerState {
value: i32,
}
struct TestLens;
impl StateLens<OuterState, InnerState> for TestLens {
fn get<'a>(&self, outer: &'a mut OuterState) -> &'a mut InnerState {
&mut outer.inner
}
}
#[test]
fn test_state_lens_projection() {
let mut outer = OuterState {
inner: InnerState { value: 42 },
other: "test".to_string(),
};
let lens = TestLens;
let inner = lens.get(&mut outer);
inner.value = 100;
assert_eq!(outer.inner.value, 100);
assert_eq!(outer.other, "test");
}
#[test]
fn test_identity_lens() {
let mut state = InnerState { value: 42 };
let lens = IdentityLens::new();
let inner = lens.get(&mut state);
inner.value = 100;
assert_eq!(state.value, 100);
}
}