1use std::fmt;
2
3use futures::future;
4use safecast::{TryCastFrom, TryCastInto};
5
6use tc_error::*;
7use tc_value::TCString;
8use tcgeneric::{Id, TCPath, Tuple};
9
10use super::{
11 DeleteHandler, GetHandler, Handler, HandlerType, PostHandler, PutHandler, StateInstance,
12};
13
14pub struct EchoHandler;
15
16impl<'a, State> Handler<'a, State> for EchoHandler
17where
18 State: StateInstance,
19{
20 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
21 where
22 'b: 'a,
23 {
24 Some(Box::new(|_txn, key| {
25 Box::pin(async move { Ok(key.into()) })
26 }))
27 }
28}
29
30pub struct ErrorHandler<'a> {
31 code: &'a Id,
32}
33
34impl<'a, State> Handler<'a, State> for ErrorHandler<'a>
35where
36 State: StateInstance,
37 TCString: TryCastFrom<State>,
38 Tuple<TCString>: TryCastFrom<State>,
39{
40 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
41 where
42 'b: 'a,
43 {
44 Some(Box::new(|_txn, key| {
45 Box::pin(async move {
46 let message: TCString =
47 key.try_cast_into(|v| TCError::unexpected(v, "an error message"))?;
48
49 if let Some(err_type) = error_type(self.code) {
50 Err(TCError::new(err_type, message.to_string()))
51 } else {
52 Err(TCError::not_found(self.code))
53 }
54 })
55 }))
56 }
57
58 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
59 where
60 'b: 'a,
61 {
62 Some(Box::new(|_txn, mut params| {
63 Box::pin(async move {
64 let message: TCString = params.require("message")?;
65 let stack: Tuple<TCString> = params.require("stack")?;
66 params.expect_empty()?;
67
68 if let Some(err_type) = error_type(self.code) {
69 Err(TCError::with_stack(err_type, message, stack))
70 } else {
71 Err(TCError::not_found(self.code))
72 }
73 })
74 }))
75 }
76}
77
78impl<'a> From<&'a Id> for ErrorHandler<'a> {
79 fn from(code: &'a Id) -> Self {
80 Self { code }
81 }
82}
83
84pub struct AttributeHandler<T> {
85 attribute: T,
86}
87
88impl<'a, State, T> Handler<'a, State> for AttributeHandler<T>
89where
90 State: StateInstance + From<T>,
91 T: Clone + Send + Sync + 'a,
92{
93 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
94 where
95 'b: 'a,
96 {
97 Some(Box::new(|_txn, key| {
98 Box::pin(async move {
99 if key.is_none() {
100 Ok(self.attribute.into())
101 } else {
102 Err(TCError::not_found(format!("attribute {key:?}")))
103 }
104 })
105 }))
106 }
107}
108
109impl<T> From<T> for AttributeHandler<T> {
110 fn from(attribute: T) -> Self {
111 Self { attribute }
112 }
113}
114
115pub struct MethodNotAllowedHandler;
116
117impl<'a, State: StateInstance> Handler<'a, State> for MethodNotAllowedHandler {
118 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
119 where
120 'b: 'a,
121 {
122 Some(Box::new(move |_txn, _key| {
123 Box::pin(future::ready(Err(TCError::method_not_allowed(
124 HandlerType::Get,
125 TCPath::default(),
126 ))))
127 }))
128 }
129
130 fn put<'b>(self: Box<Self>) -> Option<PutHandler<'a, 'b, State::Txn, State>>
131 where
132 'b: 'a,
133 {
134 Some(Box::new(move |_txn, _key, _value| {
135 Box::pin(future::ready(Err(TCError::method_not_allowed(
136 HandlerType::Put,
137 TCPath::default(),
138 ))))
139 }))
140 }
141
142 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
143 where
144 'b: 'a,
145 {
146 Some(Box::new(move |_txn, _key| {
147 Box::pin(future::ready(Err(TCError::method_not_allowed(
148 HandlerType::Post,
149 TCPath::default(),
150 ))))
151 }))
152 }
153
154 fn delete<'b>(self: Box<Self>) -> Option<DeleteHandler<'a, 'b, State::Txn>>
155 where
156 'b: 'a,
157 {
158 Some(Box::new(move |_txn, _key| {
159 Box::pin(future::ready(Err(TCError::method_not_allowed(
160 HandlerType::Delete,
161 TCPath::default(),
162 ))))
163 }))
164 }
165}
166
167pub struct SelfHandler<'a, T> {
168 subject: &'a T,
169}
170
171impl<'a, State, T> Handler<'a, State> for SelfHandler<'a, T>
172where
173 State: StateInstance + From<T>,
174 T: Clone + Send + Sync + fmt::Debug,
175{
176 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
177 where
178 'b: 'a,
179 {
180 Some(Box::new(|_txn, key| {
181 Box::pin(async move {
182 if key.is_none() {
183 Ok(self.subject.clone().into())
184 } else {
185 Err(TCError::not_found(format!(
186 "attribute {:?} of {:?}",
187 key, self.subject
188 )))
189 }
190 })
191 }))
192 }
193}
194
195impl<'a, T> From<&'a T> for SelfHandler<'a, T> {
196 fn from(subject: &'a T) -> Self {
197 Self { subject }
198 }
199}
200
201pub struct SelfHandlerOwned<T> {
202 subject: T,
203}
204
205impl<'a, State, T> Handler<'a, State> for SelfHandlerOwned<T>
206where
207 State: StateInstance + From<T>,
208 T: Send + Sync + fmt::Debug + 'a,
209{
210 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
211 where
212 'b: 'a,
213 {
214 Some(Box::new(|_txn, key| {
215 Box::pin(async move {
216 if key.is_none() {
217 Ok(self.subject.into())
218 } else {
219 Err(TCError::not_found(format!(
220 "attribute {:?} of {:?}",
221 key, self.subject
222 )))
223 }
224 })
225 }))
226 }
227}
228
229impl<'a, T> From<T> for SelfHandlerOwned<T> {
230 fn from(subject: T) -> Self {
231 Self { subject }
232 }
233}
234
235fn error_type(err_type: &Id) -> Option<ErrorKind> {
236 match err_type.as_str() {
237 "bad_gateway" => Some(ErrorKind::BadGateway),
238 "bad_request" => Some(ErrorKind::BadRequest),
239 "conflict" => Some(ErrorKind::Conflict),
240 "forbidden" => Some(ErrorKind::Forbidden),
241 "internal" => Some(ErrorKind::Internal),
242 "method_not_allowed" => Some(ErrorKind::MethodNotAllowed),
243 "not_found" => Some(ErrorKind::NotFound),
244 "not_implemented" => Some(ErrorKind::NotImplemented),
245 "timeout" => Some(ErrorKind::Timeout),
246 "unauthorized" => Some(ErrorKind::Unauthorized),
247 _ => None,
248 }
249}