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