1use std::sync::Arc;
7
8use paste::paste;
9
10use super::{
11 context::{BackendContext, BackendContextBuilder},
12 feature::{BackendFeature, CheckUp},
13};
14#[cfg(feature = "thread")]
15use crate::envelope::thread::ThreadEnvelopes;
16#[cfg(feature = "watch")]
17use crate::envelope::watch::WatchEnvelopes;
18use crate::{
19 envelope::{get::GetEnvelope, list::ListEnvelopes},
20 flag::{add::AddFlags, remove::RemoveFlags, set::SetFlags},
21 folder::{
22 add::AddFolder, delete::DeleteFolder, expunge::ExpungeFolder, list::ListFolders,
23 purge::PurgeFolder,
24 },
25 message::{
26 add::AddMessage, copy::CopyMessages, delete::DeleteMessages, get::GetMessages,
27 peek::PeekMessages, r#move::MoveMessages, remove::RemoveMessages, send::SendMessage,
28 },
29};
30
31macro_rules! some_feature_mapper {
33 ($feat:ty) => {
34 paste! {
35 fn [<$feat:snake _with_some>](
36 &self,
37 cb: &Option<CB>,
38 ) -> Option<BackendFeature<Self::Context, dyn $feat>> {
39 let cb = cb.as_ref()?;
40 self.map_feature(cb.[<$feat:snake>]())
41 }
42 }
43 };
44}
45
46pub trait SomeBackendContextBuilderMapper<CB>
53where
54 Self: BackendContextBuilder,
55 Self::Context: AsRef<Option<CB::Context>> + 'static,
56 CB: BackendContextBuilder,
57 CB::Context: BackendContext + 'static,
58{
59 fn map_feature<T: ?Sized + 'static>(
60 &self,
61 f: Option<BackendFeature<CB::Context, T>>,
62 ) -> Option<BackendFeature<Self::Context, T>> {
63 let f = f?;
64 Some(Arc::new(move |ctx| f(ctx.as_ref().as_ref()?)))
65 }
66
67 some_feature_mapper!(CheckUp);
68
69 some_feature_mapper!(AddFolder);
70 some_feature_mapper!(ListFolders);
71 some_feature_mapper!(ExpungeFolder);
72 some_feature_mapper!(PurgeFolder);
73 some_feature_mapper!(DeleteFolder);
74 some_feature_mapper!(GetEnvelope);
75 some_feature_mapper!(ListEnvelopes);
76 #[cfg(feature = "thread")]
77 some_feature_mapper!(ThreadEnvelopes);
78 #[cfg(feature = "watch")]
79 some_feature_mapper!(WatchEnvelopes);
80 some_feature_mapper!(AddFlags);
81 some_feature_mapper!(SetFlags);
82 some_feature_mapper!(RemoveFlags);
83 some_feature_mapper!(AddMessage);
84 some_feature_mapper!(SendMessage);
85 some_feature_mapper!(PeekMessages);
86 some_feature_mapper!(GetMessages);
87 some_feature_mapper!(CopyMessages);
88 some_feature_mapper!(MoveMessages);
89 some_feature_mapper!(DeleteMessages);
90 some_feature_mapper!(RemoveMessages);
91}
92
93impl<CB1, CB2> SomeBackendContextBuilderMapper<CB2> for CB1
95where
96 CB1: BackendContextBuilder,
97 CB1::Context: AsRef<Option<CB2::Context>> + 'static,
98 CB2: BackendContextBuilder,
99 CB2::Context: BackendContext + 'static,
100{
101}
102
103macro_rules! feature_mapper {
105 ($feat:ty) => {
106 paste! {
107 fn [<$feat:snake _with>] (
108 &self,
109 cb: &CB,
110 ) -> Option<BackendFeature<Self::Context, dyn $feat>> {
111 self.map_feature(cb.[<$feat:snake>]())
112 }
113 }
114 };
115}
116
117pub trait BackendContextBuilderMapper<CB>
119where
120 Self: BackendContextBuilder,
121 Self::Context: AsRef<CB::Context> + 'static,
122 CB: BackendContextBuilder,
123 CB::Context: BackendContext + 'static,
124{
125 fn map_feature<T: ?Sized + 'static>(
126 &self,
127 f: Option<BackendFeature<CB::Context, T>>,
128 ) -> Option<BackendFeature<Self::Context, T>> {
129 let f = f?;
130 Some(Arc::new(move |ctx| f(ctx.as_ref())))
131 }
132
133 feature_mapper!(AddFolder);
134 feature_mapper!(ListFolders);
135 feature_mapper!(ExpungeFolder);
136 feature_mapper!(PurgeFolder);
137 feature_mapper!(DeleteFolder);
138 feature_mapper!(GetEnvelope);
139 feature_mapper!(ListEnvelopes);
140 #[cfg(feature = "thread")]
141 feature_mapper!(ThreadEnvelopes);
142 #[cfg(feature = "watch")]
143 feature_mapper!(WatchEnvelopes);
144 feature_mapper!(AddFlags);
145 feature_mapper!(SetFlags);
146 feature_mapper!(RemoveFlags);
147 feature_mapper!(AddMessage);
148 feature_mapper!(SendMessage);
149 feature_mapper!(PeekMessages);
150 feature_mapper!(GetMessages);
151 feature_mapper!(CopyMessages);
152 feature_mapper!(MoveMessages);
153 feature_mapper!(DeleteMessages);
154 feature_mapper!(RemoveMessages);
155}
156
157impl<CB1, CB2> BackendContextBuilderMapper<CB2> for CB1
159where
160 CB1: BackendContextBuilder,
161 CB1::Context: AsRef<CB2::Context> + 'static,
162 CB2: BackendContextBuilder,
163 CB2::Context: BackendContext + 'static,
164{
165}