1#![allow(clippy::needless_doctest_main)]
2#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
3#![warn(missing_docs)]
4
5pub trait Field<Name> {
7 type Type;
9
10 fn field(self) -> Self::Type;
12}
13
14pub trait Get: Sized {
16 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
25impl<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}