cgp_field/traits/
map_field.rs

1use core::marker::PhantomData;
2
3use crate::traits::{FieldGetter, HasField};
4
5/**
6    A helper trait to help organize the lifetime inference in Rust.
7    Without this, `Self::Value` would need to be `'static`, as Rust couldn't
8    infer the correct lifetime when calling chained field getters, such as
9    `context.get_field().get_field()`.
10*/
11pub trait MapField<Tag>: HasField<Tag> {
12    fn map_field<T>(
13        &self,
14        _tag: PhantomData<Tag>,
15        mapper: impl for<'a> FnOnce(&'a Self::Value) -> &'a T,
16    ) -> &T;
17}
18
19impl<Context, Tag> MapField<Tag> for Context
20where
21    Context: HasField<Tag>,
22    Tag: 'static,
23{
24    fn map_field<T>(
25        &self,
26        tag: PhantomData<Tag>,
27        mapper: impl for<'a> FnOnce(&'a Self::Value) -> &'a T,
28    ) -> &T {
29        mapper(self.get_field(tag))
30    }
31}
32
33/**
34    The provider trait equivalent of [`MapField`].
35*/
36pub trait FieldMapper<Context, Tag>: FieldGetter<Context, Tag> {
37    fn map_field<T>(
38        context: &Context,
39        _tag: PhantomData<Tag>,
40        mapper: impl for<'a> FnOnce(&'a Self::Value) -> &'a T,
41    ) -> &T;
42}
43
44impl<Getter, Context, Tag> FieldMapper<Context, Tag> for Getter
45where
46    Getter: FieldGetter<Context, Tag> + 'static,
47    Tag: 'static,
48{
49    fn map_field<T>(
50        context: &Context,
51        tag: PhantomData<Tag>,
52        mapper: impl for<'a> FnOnce(&'a Self::Value) -> &'a T,
53    ) -> &T {
54        mapper(Getter::get_field(context, tag))
55    }
56}