pdk_classy/extract/
from_context.rs1use std::convert::Infallible;
3
4use crate::{all_the_tuples, BoxError};
5
6use self::extractability::{Direct, Extractability};
7
8mod private {
9 pub trait Sealed {}
10}
11
12pub mod extractability {
13 use super::private::Sealed;
14
15 pub trait Extractability: Sealed {}
16
17 pub enum Direct {}
18 impl Sealed for Direct {}
19 impl Extractability for Direct {}
20
21 pub enum Transitive {}
22 impl Sealed for Transitive {}
23 impl Extractability for Transitive {}
24}
25
26pub trait FromContext<C, E: Extractability = Direct>: Sized {
27 type Error: Into<BoxError>;
28
29 fn from_context(context: &C) -> Result<Self, Self::Error>;
30
31 fn from_context_always(context: &C) -> Self
32 where
33 Self: FromContext<C, E, Error = Infallible>,
34 {
35 Self::from_context(context).unwrap()
37 }
38}
39
40pub trait Extract<T> {
41 type Error;
42
43 fn extract(&self) -> Result<T, Self::Error>;
44
45 fn extract_always(&self) -> T
46 where
47 Self: Extract<T, Error = Infallible>,
48 {
49 self.extract().unwrap()
50 }
51}
52
53impl<C, T> Extract<T> for C
54where
55 T: FromContext<C>,
56{
57 type Error = T::Error;
58
59 fn extract(&self) -> Result<T, Self::Error> {
60 T::from_context(self)
61 }
62}
63
64impl<T, C> FromContext<C> for Option<T>
65where
66 T: FromContext<C>,
67{
68 type Error = Infallible;
69
70 fn from_context(context: &C) -> Result<Self, Self::Error> {
71 Ok(T::from_context(context).ok())
72 }
73}
74
75impl<T, C> FromContext<C> for Result<T, T::Error>
76where
77 T: FromContext<C>,
78{
79 type Error = Infallible;
80
81 fn from_context(context: &C) -> Result<Self, Self::Error> {
82 Ok(T::from_context(context))
83 }
84}
85
86impl<C> FromContext<C> for () {
87 type Error = Infallible;
88
89 fn from_context(_: &C) -> Result<Self, Self::Error> {
90 Ok(())
91 }
92}
93
94macro_rules! impl_from_context {
95 (
96 $($ty:ident),*
97 ) => {
98 #[allow(non_snake_case)]
99 impl<C, $($ty, )* > FromContext<C> for ($($ty,)*)
100 where
101 $( $ty: FromContext<C>, )*
102 {
103 type Error = BoxError;
104
105 fn from_context(context: &C) -> Result<Self, Self::Error> {
106 $(
107 let $ty = $ty::from_context(context).map_err(|err| err.into())?;
108 )*
109
110 Ok(($($ty,)*))
111 }
112 }
113 }
114}
115
116all_the_tuples!(impl_from_context);