cgp_field/traits/
has_field.rs1use core::marker::PhantomData;
2use core::ops::Deref;
3
4use cgp_component::UseContext;
5
6#[diagnostic::on_unimplemented(
7 message = "HasField is not implemented for {Self} with the field: {Tag}",
8 note = "You need to add #[derive(HasField)] to {Self} with the given field present in the struct"
9)]
10pub trait HasField<Tag> {
11 type Value;
12
13 fn get_field(&self, _tag: PhantomData<Tag>) -> &Self::Value;
14}
15
16pub trait FieldGetter<Context, Tag> {
17 type Value;
18
19 fn get_field(context: &Context, _tag: PhantomData<Tag>) -> &Self::Value;
20}
21
22#[diagnostic::do_not_recommend]
23impl<Context, Tag, Target, Value> HasField<Tag> for Context
24where
25 Context: DerefMap<Target = Target>,
26 Target: HasField<Tag, Value = Value>,
27{
28 type Value = Value;
29
30 fn get_field(&self, tag: PhantomData<Tag>) -> &Self::Value {
31 self.map_deref(|context| context.get_field(tag))
32 }
33}
34
35impl<Context, Tag, Field> FieldGetter<Context, Tag> for UseContext
36where
37 Context: HasField<Tag, Value = Field>,
38{
39 type Value = Field;
40
41 fn get_field(context: &Context, _tag: PhantomData<Tag>) -> &Self::Value {
42 context.get_field(PhantomData)
43 }
44}
45
46trait DerefMap: Deref {
52 fn map_deref<T>(&self, mapper: impl for<'a> FnOnce(&'a Self::Target) -> &'a T) -> &T;
53}
54
55impl<Context> DerefMap for Context
56where
57 Context: Deref,
58{
59 fn map_deref<T>(&self, mapper: impl for<'a> FnOnce(&'a Self::Target) -> &'a T) -> &T {
60 mapper(self.deref())
61 }
62}