cgp_field/traits/
has_field.rs1use core::marker::PhantomData;
2use core::ops::Deref;
3
4use cgp_component::UseContext;
5
6#[diagnostic::on_unimplemented(
47 message = "HasField is not implemented for {Self} with the field: {Tag}",
48 note = "You need to add #[derive(HasField)] to {Self} with the given field present in the struct"
49)]
50pub trait HasField<Tag> {
51 type Value;
52
53 fn get_field(&self, _tag: PhantomData<Tag>) -> &Self::Value;
54}
55
56pub trait FieldGetter<Context, Tag> {
57 type Value;
58
59 fn get_field(context: &Context, _tag: PhantomData<Tag>) -> &Self::Value;
60}
61
62#[diagnostic::do_not_recommend]
63impl<Context, Tag, Target, Value> HasField<Tag> for Context
64where
65 Context: DerefMap<Target = Target>,
66 Target: HasField<Tag, Value = Value>,
67{
68 type Value = Value;
69
70 fn get_field(&self, tag: PhantomData<Tag>) -> &Self::Value {
71 self.map_deref(|context| context.get_field(tag))
72 }
73}
74
75impl<Context, Tag, Field> FieldGetter<Context, Tag> for UseContext
76where
77 Context: HasField<Tag, Value = Field>,
78{
79 type Value = Field;
80
81 fn get_field(context: &Context, _tag: PhantomData<Tag>) -> &Self::Value {
82 context.get_field(PhantomData)
83 }
84}
85
86trait DerefMap: Deref {
92 fn map_deref<T>(&self, mapper: impl for<'a> FnOnce(&'a Self::Target) -> &'a T) -> &T;
93}
94
95impl<Context> DerefMap for Context
96where
97 Context: Deref,
98{
99 fn map_deref<T>(&self, mapper: impl for<'a> FnOnce(&'a Self::Target) -> &'a T) -> &T {
100 mapper(self.deref())
101 }
102}