pub struct Kp<R, V, Root, Value, MutRoot, MutValue, G, S>where
Root: Borrow<R>,
MutRoot: BorrowMut<R>,
MutValue: BorrowMut<V>,
G: Fn(Root) -> Option<Value>,
S: Fn(MutRoot) -> Option<MutValue>,{ /* private fields */ }Expand description
AKp (AnyKeyPath) - Hides both Root and Value types Most flexible keypath type for heterogeneous collections Uses dynamic dispatch and type checking at runtime
§Mutation: get vs get_mut (setter path)
- get uses the
getclosure (getter):Fn(Root) -> Option<Value> - get_mut uses the
setclosure (setter):Fn(MutRoot) -> Option<MutValue>
When mutating through a Kp, the setter path is used—get_mut invokes the set closure,
not the get closure. The getter is for read-only access only.
Implementations§
Source§impl<R, V> Kp<R, V, &'static R, &'static V, &'static mut R, &'static mut V, Box<dyn for<'b> Fn(&'b R) -> Option<&'b V>>, Box<dyn for<'b> Fn(&'b mut R) -> Option<&'b mut V>>>
impl<R, V> Kp<R, V, &'static R, &'static V, &'static mut R, &'static mut V, Box<dyn for<'b> Fn(&'b R) -> Option<&'b V>>, Box<dyn for<'b> Fn(&'b mut R) -> Option<&'b mut V>>>
Sourcepub fn from_closures<G, S>(get: G, set: S) -> Self
pub fn from_closures<G, S>(get: G, set: S) -> Self
Build a keypath from two closures (e.g. when they capture a variable like an index).
Same pattern as Kp::new in lock.rs; use this when the keypath captures variables.
Source§impl<R, V, Root, Value, MutRoot, MutValue, G, S> Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
impl<R, V, Root, Value, MutRoot, MutValue, G, S> Kp<R, V, Root, Value, MutRoot, MutValue, G, S>
pub fn new(get: G, set: S) -> Self
pub fn get(&self, root: Root) -> Option<Value>
pub fn get_mut(&self, root: MutRoot) -> Option<MutValue>
pub fn then<SV, SubValue, MutSubValue, G2, S2>( self, next: Kp<V, SV, Value, SubValue, MutValue, MutSubValue, G2, S2>, ) -> Kp<R, SV, Root, SubValue, MutRoot, MutSubValue, impl Fn(Root) -> Option<SubValue> + use<SV, SubValue, MutSubValue, G2, S2, R, V, Root, Value, MutRoot, MutValue, G, S>, impl Fn(MutRoot) -> Option<MutSubValue> + use<SV, SubValue, MutSubValue, G2, S2, R, V, Root, Value, MutRoot, MutValue, G, S>>
Sourcepub fn then_lock<Lock, Mid, V2, LockValue, MidValue, Value2, MutLock, MutMid, MutValue2, G1, S1, L, G2, S2>(
self,
lock_kp: LockKp<V, Lock, Mid, V2, Value, LockValue, MidValue, Value2, MutValue, MutLock, MutMid, MutValue2, G1, S1, L, G2, S2>,
) -> KpThenLockKp<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, Self, LockKp<V, Lock, Mid, V2, Value, LockValue, MidValue, Value2, MutValue, MutLock, MutMid, MutValue2, G1, S1, L, G2, S2>>where
V: 'static + Clone,
V2: 'static,
Value: Borrow<V>,
Value2: Borrow<V2>,
MutValue: BorrowMut<V>,
MutValue2: BorrowMut<V2>,
LockValue: Borrow<Lock>,
MidValue: Borrow<Mid>,
MutLock: BorrowMut<Lock>,
MutMid: BorrowMut<Mid>,
G1: Fn(Value) -> Option<LockValue>,
S1: Fn(MutValue) -> Option<MutLock>,
L: LockAccess<Lock, MidValue> + LockAccess<Lock, MutMid>,
G2: Fn(MidValue) -> Option<Value2>,
S2: Fn(MutMid) -> Option<MutValue2>,
pub fn then_lock<Lock, Mid, V2, LockValue, MidValue, Value2, MutLock, MutMid, MutValue2, G1, S1, L, G2, S2>(
self,
lock_kp: LockKp<V, Lock, Mid, V2, Value, LockValue, MidValue, Value2, MutValue, MutLock, MutMid, MutValue2, G1, S1, L, G2, S2>,
) -> KpThenLockKp<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, Self, LockKp<V, Lock, Mid, V2, Value, LockValue, MidValue, Value2, MutValue, MutLock, MutMid, MutValue2, G1, S1, L, G2, S2>>where
V: 'static + Clone,
V2: 'static,
Value: Borrow<V>,
Value2: Borrow<V2>,
MutValue: BorrowMut<V>,
MutValue2: BorrowMut<V2>,
LockValue: Borrow<Lock>,
MidValue: Borrow<Mid>,
MutLock: BorrowMut<Lock>,
MutMid: BorrowMut<Mid>,
G1: Fn(Value) -> Option<LockValue>,
S1: Fn(MutValue) -> Option<MutLock>,
L: LockAccess<Lock, MidValue> + LockAccess<Lock, MutMid>,
G2: Fn(MidValue) -> Option<Value2>,
S2: Fn(MutMid) -> Option<MutValue2>,
Chain with a sync crate::lock::LockKp. Use .get(root) / .get_mut(root) on the returned keypath.
Sourcepub fn then_async<AsyncKp>(
self,
async_kp: AsyncKp,
) -> KpThenAsyncKeyPath<R, V, <AsyncKp::Value as KeyPathValueTarget>::Target, Root, Value, AsyncKp::Value, MutRoot, MutValue, AsyncKp::MutValue, Self, AsyncKp>where
V: 'static,
Value: Borrow<V>,
MutValue: BorrowMut<V>,
AsyncKp: AsyncKeyPathLike<Value, MutValue>,
AsyncKp::Value: KeyPathValueTarget + Borrow<<AsyncKp::Value as KeyPathValueTarget>::Target>,
AsyncKp::MutValue: BorrowMut<<AsyncKp::Value as KeyPathValueTarget>::Target>,
<AsyncKp::Value as KeyPathValueTarget>::Target: 'static,
pub fn then_async<AsyncKp>(
self,
async_kp: AsyncKp,
) -> KpThenAsyncKeyPath<R, V, <AsyncKp::Value as KeyPathValueTarget>::Target, Root, Value, AsyncKp::Value, MutRoot, MutValue, AsyncKp::MutValue, Self, AsyncKp>where
V: 'static,
Value: Borrow<V>,
MutValue: BorrowMut<V>,
AsyncKp: AsyncKeyPathLike<Value, MutValue>,
AsyncKp::Value: KeyPathValueTarget + Borrow<<AsyncKp::Value as KeyPathValueTarget>::Target>,
AsyncKp::MutValue: BorrowMut<<AsyncKp::Value as KeyPathValueTarget>::Target>,
<AsyncKp::Value as KeyPathValueTarget>::Target: 'static,
Chain with an async keypath (e.g. crate::async_lock::AsyncLockKp). Use .get(&root).await on the returned keypath.
When AsyncKp::Value is a reference type (&T / &mut T), V2 is inferred as T via KeyPathValueTarget.
Sourcepub fn map<MappedValue, F>(
&self,
mapper: F,
) -> Kp<R, MappedValue, Root, MappedValue, MutRoot, MappedValue, impl Fn(Root) -> Option<MappedValue>, impl Fn(MutRoot) -> Option<MappedValue>>
pub fn map<MappedValue, F>( &self, mapper: F, ) -> Kp<R, MappedValue, Root, MappedValue, MutRoot, MappedValue, impl Fn(Root) -> Option<MappedValue>, impl Fn(MutRoot) -> Option<MappedValue>>
Map the value through a transformation function Returns a new keypath that transforms the value when accessed
§Example
use rust_key_paths::{Kp, KpType};
struct User { name: String }
let user = User { name: "Alice".to_string() };
let name_kp = KpType::new(|u: &User| Some(&u.name), |u: &mut User| Some(&mut u.name));
let len_kp = name_kp.map(|name: &String| name.len());
assert_eq!(len_kp.get(&user), Some(5));Sourcepub fn filter<F>(
&self,
predicate: F,
) -> Kp<R, V, Root, Value, MutRoot, MutValue, impl Fn(Root) -> Option<Value>, impl Fn(MutRoot) -> Option<MutValue>>
pub fn filter<F>( &self, predicate: F, ) -> Kp<R, V, Root, Value, MutRoot, MutValue, impl Fn(Root) -> Option<Value>, impl Fn(MutRoot) -> Option<MutValue>>
Filter the value based on a predicate Returns None if the predicate returns false, otherwise returns the value
§Example
use rust_key_paths::{Kp, KpType};
struct User { age: i32 }
let user = User { age: 30 };
let age_kp = KpType::new(|u: &User| Some(&u.age), |u: &mut User| Some(&mut u.age));
let adult_kp = age_kp.filter(|age: &i32| *age >= 18);
assert_eq!(adult_kp.get(&user), Some(&30));Sourcepub fn filter_map<MappedValue, F>(
&self,
mapper: F,
) -> Kp<R, MappedValue, Root, MappedValue, MutRoot, MappedValue, impl Fn(Root) -> Option<MappedValue>, impl Fn(MutRoot) -> Option<MappedValue>>
pub fn filter_map<MappedValue, F>( &self, mapper: F, ) -> Kp<R, MappedValue, Root, MappedValue, MutRoot, MappedValue, impl Fn(Root) -> Option<MappedValue>, impl Fn(MutRoot) -> Option<MappedValue>>
Map and flatten - useful when mapper returns an Option
§Example
use rust_key_paths::{Kp, KpType};
struct User { middle_name: Option<String> }
let user = User { middle_name: Some("M.".to_string()) };
let middle_kp = KpType::new(|u: &User| Some(&u.middle_name), |_| None);
let first_char_kp = middle_kp.filter_map(|opt: &Option<String>| {
opt.as_ref().and_then(|s| s.chars().next())
});Sourcepub fn flat_map<I, Item, F>(&self, mapper: F) -> impl Fn(Root) -> Vec<Item>
pub fn flat_map<I, Item, F>(&self, mapper: F) -> impl Fn(Root) -> Vec<Item>
Flat map - maps to an iterator and flattens Useful when the value is a collection and you want to iterate over it
§Example
use rust_key_paths::{Kp, KpType};
struct User { tags: Vec<&'static str> }
let user = User { tags: vec!["rust", "web"] };
let tags_kp = KpType::new(|u: &User| Some(&u.tags), |_| None);
// Use with a closure that returns an iteratorSourcepub fn inspect<F>(
&self,
inspector: F,
) -> Kp<R, V, Root, Value, MutRoot, MutValue, impl Fn(Root) -> Option<Value>, impl Fn(MutRoot) -> Option<MutValue>>
pub fn inspect<F>( &self, inspector: F, ) -> Kp<R, V, Root, Value, MutRoot, MutValue, impl Fn(Root) -> Option<Value>, impl Fn(MutRoot) -> Option<MutValue>>
Apply a function for its side effects and return the value
§Example
use rust_key_paths::{Kp, KpType};
struct User { name: String }
let user = User { name: "Alice".to_string() };
let name_kp = KpType::new(|u: &User| Some(&u.name), |_| None);
name_kp.inspect(|name| println!("Name: {}", name)).get(&user);Sourcepub fn fold_value<Acc, F>(&self, init: Acc, folder: F) -> impl Fn(Root) -> Acc
pub fn fold_value<Acc, F>(&self, init: Acc, folder: F) -> impl Fn(Root) -> Acc
Fold/reduce the value using an accumulator function Useful when the value is a collection
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 78] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let sum = scores_kp.fold_value(0, |acc, scores| {
scores.iter().sum::<i32>() + acc
})(&user);Sourcepub fn any<F>(&self, predicate: F) -> impl Fn(Root) -> bool
pub fn any<F>(&self, predicate: F) -> impl Fn(Root) -> bool
Check if any element satisfies a predicate (for collection values)
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 78] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let has_high = scores_kp.any(|scores| scores.iter().any(|&s| s > 90));
assert!(has_high(&user));Sourcepub fn all<F>(&self, predicate: F) -> impl Fn(Root) -> bool
pub fn all<F>(&self, predicate: F) -> impl Fn(Root) -> bool
Check if all elements satisfy a predicate (for collection values)
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 78] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let all_passing = scores_kp.all(|scores| scores.iter().all(|&s| s >= 70));
assert!(all_passing(&user));Sourcepub fn count_items<F>(&self, counter: F) -> impl Fn(Root) -> Option<usize>
pub fn count_items<F>(&self, counter: F) -> impl Fn(Root) -> Option<usize>
Count elements in a collection value
§Example
use rust_key_paths::{Kp, KpType};
struct User { tags: Vec<&'static str> }
let user = User { tags: vec!["rust", "web", "backend"] };
let tags_kp = KpType::new(|u: &User| Some(&u.tags), |_| None);
let count = tags_kp.count_items(|tags| tags.len());
assert_eq!(count(&user), Some(3));Sourcepub fn find_in<Item, F>(&self, finder: F) -> impl Fn(Root) -> Option<Item>
pub fn find_in<Item, F>(&self, finder: F) -> impl Fn(Root) -> Option<Item>
Find first element matching predicate in a collection value
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 78, 95] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let first_high = scores_kp.find_in(|scores| {
scores.iter().find(|&&s| s > 90).copied()
});
assert_eq!(first_high(&user), Some(92));Sourcepub fn take<Output, F>(
&self,
n: usize,
taker: F,
) -> impl Fn(Root) -> Option<Output>
pub fn take<Output, F>( &self, n: usize, taker: F, ) -> impl Fn(Root) -> Option<Output>
Take first N elements from a collection value
§Example
use rust_key_paths::{Kp, KpType};
struct User { tags: Vec<&'static str> }
let user = User { tags: vec!["a", "b", "c", "d"] };
let tags_kp = KpType::new(|u: &User| Some(&u.tags), |_| None);
let first_two = tags_kp.take(2, |tags, n| tags.iter().take(n).cloned().collect::<Vec<_>>());Sourcepub fn skip<Output, F>(
&self,
n: usize,
skipper: F,
) -> impl Fn(Root) -> Option<Output>
pub fn skip<Output, F>( &self, n: usize, skipper: F, ) -> impl Fn(Root) -> Option<Output>
Skip first N elements from a collection value
§Example
use rust_key_paths::{Kp, KpType};
struct User { tags: Vec<&'static str> }
let user = User { tags: vec!["a", "b", "c", "d"] };
let tags_kp = KpType::new(|u: &User| Some(&u.tags), |_| None);
let after_two = tags_kp.skip(2, |tags, n| tags.iter().skip(n).cloned().collect::<Vec<_>>());Sourcepub fn partition_value<Output, F>(
&self,
partitioner: F,
) -> impl Fn(Root) -> Option<Output>
pub fn partition_value<Output, F>( &self, partitioner: F, ) -> impl Fn(Root) -> Option<Output>
Partition a collection value into two groups based on predicate
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 65, 95, 72] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let (passing, failing): (Vec<i32>, Vec<i32>) = scores_kp.partition_value(|scores| {
scores.iter().copied().partition(|&s| s >= 70)
})(&user).unwrap();Sourcepub fn min_value<Item, F>(&self, min_fn: F) -> impl Fn(Root) -> Option<Item>
pub fn min_value<Item, F>(&self, min_fn: F) -> impl Fn(Root) -> Option<Item>
Get min value from a collection
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 78] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let min = scores_kp.min_value(|scores| scores.iter().min().copied());
assert_eq!(min(&user), Some(78));Sourcepub fn max_value<Item, F>(&self, max_fn: F) -> impl Fn(Root) -> Option<Item>
pub fn max_value<Item, F>(&self, max_fn: F) -> impl Fn(Root) -> Option<Item>
Get max value from a collection
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 78] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let max = scores_kp.max_value(|scores| scores.iter().max().copied());
assert_eq!(max(&user), Some(92));Sourcepub fn sum_value<Sum, F>(&self, sum_fn: F) -> impl Fn(Root) -> Option<Sum>
pub fn sum_value<Sum, F>(&self, sum_fn: F) -> impl Fn(Root) -> Option<Sum>
Sum numeric values in a collection
§Example
use rust_key_paths::{Kp, KpType};
struct User { scores: Vec<i32> }
let user = User { scores: vec![85, 92, 78] };
let scores_kp = KpType::new(|u: &User| Some(&u.scores), |_| None);
let sum = scores_kp.sum_value(|scores: &Vec<i32>| scores.iter().sum());
assert_eq!(sum(&user), Some(255));Sourcepub fn chain<SV, SubValue, MutSubValue, G2, S2>(
self,
next: Kp<V, SV, Value, SubValue, MutValue, MutSubValue, G2, S2>,
) -> Kp<R, SV, Root, SubValue, MutRoot, MutSubValue, impl Fn(Root) -> Option<SubValue>, impl Fn(MutRoot) -> Option<MutSubValue>>
pub fn chain<SV, SubValue, MutSubValue, G2, S2>( self, next: Kp<V, SV, Value, SubValue, MutValue, MutSubValue, G2, S2>, ) -> Kp<R, SV, Root, SubValue, MutRoot, MutSubValue, impl Fn(Root) -> Option<SubValue>, impl Fn(MutRoot) -> Option<MutSubValue>>
Chain this keypath with another to create a composition
Alias for then with a more descriptive name