modifier/
lib.rs

1#![deny(missing_docs, warnings)]
2
3//! Overloadable modification through both owned and mutable references
4//! to a type with minimal code duplication.
5
6/// Allows use of the implemented type as an argument to Set::set.
7///
8/// This allows types to be used for ad-hoc overloading of Set::set
9/// to perform complex updates to the parameter of Modifier.
10pub trait Modifier<F: ?Sized> {
11    /// Modify `F` with self.
12    fn modify(self, &mut F);
13}
14
15/// A trait providing the set and set_mut methods for all types.
16///
17/// Simply implement this for your types and they can be used
18/// with modifiers.
19pub trait Set {
20    /// Modify self using the provided modifier.
21    #[inline(always)]
22    fn set<M: Modifier<Self>>(mut self, modifier: M) -> Self where Self: Sized {
23        modifier.modify(&mut self);
24        self
25    }
26
27    /// Modify self through a mutable reference with the provided modifier.
28    #[inline(always)]
29    fn set_mut<M: Modifier<Self>>(&mut self, modifier: M) -> &mut Self {
30        modifier.modify(self);
31        self
32    }
33}
34
35mod impls;
36
37#[cfg(test)]
38mod test {
39    pub use super::*;
40
41    pub struct Thing {
42        x: usize
43    }
44
45    impl Set for Thing {}
46
47    pub struct ModifyX(usize);
48
49    impl Modifier<Thing> for ModifyX {
50        fn modify(self, thing: &mut Thing) {
51            let ModifyX(val) = self;
52            thing.x = val;
53        }
54    }
55
56    #[test]
57    fn test_set_and_set_mut() {
58        let mut thing = Thing { x: 6 };
59        thing.set_mut(ModifyX(8));
60        assert_eq!(thing.x, 8);
61
62        let thing = thing.set(ModifyX(9));
63        assert_eq!(thing.x, 9);
64    }
65
66    #[test]
67    fn test_tuple_chains() {
68        let thing = Thing { x: 8 }.set((ModifyX(5), ModifyX(112)));
69        assert_eq!(thing.x, 112);
70    }
71}
72