abstract_getters/
lib.rs

1#![allow(clippy::needless_doctest_main)]
2#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
3#![warn(missing_docs)]
4
5/// Defines a [Field] for a struct with a specific [type](Field::Type).
6pub trait Field<Name> {
7    /// The type of the field.
8    type Type;
9
10    /// Returns the value of the field.
11    fn field(self) -> Self::Type;
12}
13
14/// A trait for [Get]ting a value from a specific [Field] with a specific [Field::Type].
15pub trait Get: Sized {
16    /// Returns a value of a [field](Field) called `Name`.
17    fn get<Name>(self) -> <Self as Field<Name>>::Type
18    where
19        Self: Field<Name>,
20    {
21        <Self as Field<Name>>::field(self)
22    }
23}
24
25/// Allow to get field from all types.
26impl<T> Get for T {}
27
28#[cfg(test)]
29mod tests {
30    use foo::{Bar, Baz};
31
32    use super::*;
33
34    #[derive(Debug, Clone)]
35    struct Foo {
36        foo: i32,
37        bar: String,
38        baz: String,
39    }
40
41    mod foo {
42        use crate::Field;
43
44        pub struct Foo;
45        impl Field<Foo> for super::Foo {
46            type Type = i32;
47            fn field(self) -> Self::Type {
48                self.foo
49            }
50        }
51        impl<'a> Field<Foo> for &'a super::Foo {
52            type Type = &'a i32;
53            fn field(self) -> Self::Type {
54                &self.foo
55            }
56        }
57        impl<'a> Field<Foo> for &'a mut super::Foo {
58            type Type = &'a mut i32;
59            fn field(self) -> Self::Type {
60                &mut self.foo
61            }
62        }
63
64        pub struct Bar;
65        impl Field<Bar> for super::Foo {
66            type Type = String;
67            fn field(self) -> Self::Type {
68                self.bar
69            }
70        }
71        impl<'a> Field<Bar> for &'a super::Foo {
72            type Type = &'a String;
73            fn field(self) -> Self::Type {
74                &self.bar
75            }
76        }
77        impl<'a> Field<Bar> for &'a mut super::Foo {
78            type Type = &'a mut String;
79            fn field(self) -> Self::Type {
80                &mut self.bar
81            }
82        }
83
84        pub struct Baz;
85        impl Field<Baz> for super::Foo {
86            type Type = String;
87            fn field(self) -> Self::Type {
88                self.baz
89            }
90        }
91        impl<'a> Field<Baz> for &'a super::Foo {
92            type Type = &'a String;
93            fn field(self) -> Self::Type {
94                &self.baz
95            }
96        }
97        impl<'a> Field<Baz> for &'a mut super::Foo {
98            type Type = &'a mut String;
99            fn field(self) -> Self::Type {
100                &mut self.baz
101            }
102        }
103    }
104
105    pub struct Foo2<'a, T> {
106        number: T,
107        re: &'a str,
108    }
109
110    mod foo2 {
111        use super::Field;
112        pub struct Number;
113
114        impl<T> Field<Number> for super::Foo2<'_, T> {
115            type Type = T;
116            fn field(self) -> Self::Type {
117                self.number
118            }
119        }
120
121        impl<'top: 't, 't, T> Field<Number> for &'top super::Foo2<'t, T> {
122            type Type = &'t T;
123            fn field(self) -> Self::Type {
124                &self.number
125            }
126        }
127
128        impl<'top: 't, 't, T> Field<Number> for &'top mut super::Foo2<'t, T> {
129            type Type = &'t mut T;
130            fn field(self) -> Self::Type {
131                &mut self.number
132            }
133        }
134
135        pub struct Re;
136
137        impl<'a, T> Field<Re> for super::Foo2<'a, T> {
138            type Type = &'a str;
139            fn field(self) -> Self::Type {
140                self.re
141            }
142        }
143
144        impl<'top, 't, T> Field<Re> for &'top super::Foo2<'t, T> {
145            type Type = &'top &'t str;
146            fn field(self) -> Self::Type {
147                &self.re
148            }
149        }
150
151        impl<'top, 't, T> Field<Re> for &'top mut super::Foo2<'t, T> {
152            type Type = &'top mut &'t str;
153            fn field(self) -> Self::Type {
154                &mut self.re
155            }
156        }
157    }
158
159    #[test]
160    fn test_foo() {
161        let mut foo = Foo {
162            foo: 42,
163            bar: "Hello".to_string(),
164            baz: "World".to_string(),
165        };
166
167        let _bar_ref: &String = (&foo).get::<Bar>();
168        let _bar_mut: &mut String = (&mut foo).get::<Bar>();
169        let _bar_val: String = foo.clone().get::<Bar>();
170
171        let _baz_ref: &String = (&foo).get::<Baz>();
172        let _baz_mut: &mut String = (&mut foo).get::<Baz>();
173        let _baz_val: String = foo.clone().get::<Baz>();
174
175        let _foo_ref: &i32 = (&foo).get::<foo::Foo>();
176        let _foo_mut: &mut i32 = (&mut foo).get::<foo::Foo>();
177        let _foo_val: i32 = foo.clone().get::<foo::Foo>();
178    }
179
180    #[test]
181    fn test_foo2() {
182        let mut foo2 = Foo2 {
183            number: 42,
184            re: "Hello",
185        };
186
187        let _re: &i32 = (&foo2).get::<foo2::Number>();
188        assert_eq!(_re, &foo2.number);
189
190        let re: &str = (&foo2).get::<foo2::Re>();
191        assert_eq!(re, foo2.re);
192        let _re: &mut &str = (&mut foo2).get::<foo2::Re>();
193        let _re: &str = foo2.get::<foo2::Re>();
194    }
195}