Skip to main content

embedded_svc/http/
client.rs

1use crate::io::{Error, ErrorType, Read, Write};
2
3pub use super::{Headers, Method, Status};
4
5#[derive(Debug)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7pub struct Client<C>(C);
8
9impl<C> Client<C>
10where
11    C: Connection,
12{
13    pub fn wrap(connection: C) -> Self {
14        if connection.is_request_initiated() || connection.is_response_initiated() {
15            panic!("connection is not in initial phase");
16        }
17
18        Self(connection)
19    }
20
21    pub fn connection(&mut self) -> &mut C {
22        &mut self.0
23    }
24
25    pub fn release(self) -> C {
26        self.0
27    }
28
29    pub fn get<'a>(&'a mut self, uri: &'a str) -> Result<Request<&'a mut C>, C::Error> {
30        self.request(Method::Get, uri, &[])
31    }
32
33    pub fn post<'a>(
34        &'a mut self,
35        uri: &'a str,
36        headers: &'a [(&'a str, &'a str)],
37    ) -> Result<Request<&'a mut C>, C::Error> {
38        self.request(Method::Post, uri, headers)
39    }
40
41    pub fn put<'a>(
42        &'a mut self,
43        uri: &'a str,
44        headers: &'a [(&'a str, &'a str)],
45    ) -> Result<Request<&'a mut C>, C::Error> {
46        self.request(Method::Put, uri, headers)
47    }
48
49    pub fn delete<'a>(&'a mut self, uri: &'a str) -> Result<Request<&'a mut C>, C::Error> {
50        self.request(Method::Delete, uri, &[])
51    }
52
53    pub fn request<'a>(
54        &'a mut self,
55        method: Method,
56        uri: &'a str,
57        headers: &'a [(&'a str, &'a str)],
58    ) -> Result<Request<&'a mut C>, C::Error> {
59        self.0.initiate_request(method, uri, headers)?;
60
61        Ok(Request::wrap(&mut self.0))
62    }
63
64    pub fn raw_connection(&mut self) -> Result<&mut C::RawConnection, C::Error> {
65        self.0.raw_connection()
66    }
67}
68
69impl<C> ErrorType for Client<C>
70where
71    C: ErrorType,
72{
73    type Error = C::Error;
74}
75
76#[derive(Debug)]
77#[cfg_attr(feature = "defmt", derive(defmt::Format))]
78pub struct Request<C>(C);
79
80impl<C> Request<C>
81where
82    C: Connection,
83{
84    pub fn wrap(connection: C) -> Request<C> {
85        if !connection.is_request_initiated() {
86            panic!("connection is not in request phase");
87        }
88
89        Request(connection)
90    }
91
92    pub fn submit(mut self) -> Result<Response<C>, C::Error> {
93        self.0.initiate_response()?;
94
95        Ok(Response(self.0))
96    }
97
98    pub fn connection(&mut self) -> &mut C {
99        &mut self.0
100    }
101
102    pub fn release(self) -> C {
103        self.0
104    }
105
106    pub fn write(&mut self, buf: &[u8]) -> Result<usize, C::Error> {
107        self.0.write(buf)
108    }
109
110    pub fn flush(&mut self) -> Result<(), C::Error> {
111        self.0.flush()
112    }
113}
114
115impl<C> ErrorType for Request<C>
116where
117    C: ErrorType,
118{
119    type Error = C::Error;
120}
121
122impl<C> Write for Request<C>
123where
124    C: Connection,
125{
126    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
127        self.0.write(buf)
128    }
129
130    fn flush(&mut self) -> Result<(), Self::Error> {
131        self.0.flush()
132    }
133}
134
135#[derive(Debug)]
136#[cfg_attr(feature = "defmt", derive(defmt::Format))]
137pub struct Response<C>(C);
138
139impl<C> Response<C>
140where
141    C: Connection,
142{
143    pub fn wrap(connection: C) -> Response<C> {
144        if !connection.is_response_initiated() {
145            panic!("connection is not in response phase");
146        }
147
148        Response(connection)
149    }
150
151    pub fn split(&mut self) -> (&C::Headers, &mut C::Read) {
152        self.0.split()
153    }
154
155    pub fn connection(&mut self) -> &mut C {
156        &mut self.0
157    }
158
159    pub fn release(self) -> C {
160        self.0
161    }
162
163    pub fn status(&self) -> u16 {
164        self.0.status()
165    }
166
167    pub fn status_message(&self) -> Option<&'_ str> {
168        self.0.status_message()
169    }
170
171    pub fn header(&self, name: &str) -> Option<&'_ str> {
172        self.0.header(name)
173    }
174
175    pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, C::Error> {
176        self.0.read(buf)
177    }
178}
179
180impl<C> Status for Response<C>
181where
182    C: Connection,
183{
184    fn status(&self) -> u16 {
185        Response::status(self)
186    }
187
188    fn status_message(&self) -> Option<&'_ str> {
189        Response::status_message(self)
190    }
191}
192
193impl<C> Headers for Response<C>
194where
195    C: Connection,
196{
197    fn header(&self, name: &str) -> Option<&'_ str> {
198        Response::header(self, name)
199    }
200}
201
202impl<C> ErrorType for Response<C>
203where
204    C: ErrorType,
205{
206    type Error = C::Error;
207}
208
209impl<C> Read for Response<C>
210where
211    C: Connection,
212{
213    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
214        Response::read(self, buf)
215    }
216}
217
218pub trait Connection: Status + Headers + Read + Write {
219    type Headers: Status + Headers;
220
221    type Read: Read<Error = Self::Error>;
222
223    type RawConnectionError: Error;
224
225    type RawConnection: Read<Error = Self::RawConnectionError>
226        + Write<Error = Self::RawConnectionError>;
227
228    fn initiate_request<'a>(
229        &'a mut self,
230        method: Method,
231        uri: &'a str,
232        headers: &'a [(&'a str, &'a str)],
233    ) -> Result<(), Self::Error>;
234
235    fn is_request_initiated(&self) -> bool;
236
237    fn initiate_response(&mut self) -> Result<(), Self::Error>;
238
239    fn is_response_initiated(&self) -> bool;
240
241    fn split(&mut self) -> (&Self::Headers, &mut Self::Read);
242
243    fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error>;
244}
245
246impl<C> Connection for &mut C
247where
248    C: Connection,
249{
250    type Headers = C::Headers;
251
252    type Read = C::Read;
253
254    type RawConnectionError = C::RawConnectionError;
255
256    type RawConnection = C::RawConnection;
257
258    fn initiate_request<'a>(
259        &'a mut self,
260        method: Method,
261        uri: &'a str,
262        headers: &'a [(&'a str, &'a str)],
263    ) -> Result<(), Self::Error> {
264        (*self).initiate_request(method, uri, headers)
265    }
266
267    fn is_request_initiated(&self) -> bool {
268        (**self).is_request_initiated()
269    }
270
271    fn initiate_response(&mut self) -> Result<(), Self::Error> {
272        (*self).initiate_response()
273    }
274
275    fn is_response_initiated(&self) -> bool {
276        (**self).is_response_initiated()
277    }
278
279    fn split(&mut self) -> (&Self::Headers, &mut Self::Read) {
280        (*self).split()
281    }
282
283    fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error> {
284        (*self).raw_connection()
285    }
286}
287
288pub mod asynch {
289    use crate::io::{asynch::Read, asynch::Write, Error, ErrorType};
290
291    pub use crate::http::asynch::*;
292    pub use crate::http::{Headers, Method, Status};
293
294    #[derive(Debug)]
295    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
296    pub struct Client<C>(C);
297
298    impl<C> Client<C>
299    where
300        C: Connection,
301    {
302        pub fn wrap(connection: C) -> Self {
303            if connection.is_request_initiated() || connection.is_response_initiated() {
304                panic!("connection is not in initial phase");
305            }
306
307            Self(connection)
308        }
309
310        pub fn connection(&mut self) -> &mut C {
311            &mut self.0
312        }
313
314        pub fn release(self) -> C {
315            self.0
316        }
317
318        pub async fn get<'a>(&'a mut self, uri: &'a str) -> Result<Request<&'a mut C>, C::Error> {
319            self.request(Method::Get, uri, &[]).await
320        }
321
322        pub async fn post<'a>(
323            &'a mut self,
324            uri: &'a str,
325            headers: &'a [(&'a str, &'a str)],
326        ) -> Result<Request<&'a mut C>, C::Error> {
327            self.request(Method::Post, uri, headers).await
328        }
329
330        pub async fn put<'a>(
331            &'a mut self,
332            uri: &'a str,
333            headers: &'a [(&'a str, &'a str)],
334        ) -> Result<Request<&'a mut C>, C::Error> {
335            self.request(Method::Put, uri, headers).await
336        }
337
338        pub async fn delete<'a>(
339            &'a mut self,
340            uri: &'a str,
341        ) -> Result<Request<&'a mut C>, C::Error> {
342            self.request(Method::Delete, uri, &[]).await
343        }
344
345        pub async fn request<'a>(
346            &'a mut self,
347            method: Method,
348            uri: &'a str,
349            headers: &'a [(&'a str, &'a str)],
350        ) -> Result<Request<&'a mut C>, C::Error> {
351            self.0.initiate_request(method, uri, headers).await?;
352
353            Ok(Request::wrap(&mut self.0))
354        }
355
356        pub fn raw_connection(&mut self) -> Result<&mut C::RawConnection, C::Error> {
357            self.0.raw_connection()
358        }
359    }
360
361    impl<C> ErrorType for Client<C>
362    where
363        C: ErrorType,
364    {
365        type Error = C::Error;
366    }
367
368    #[derive(Debug)]
369    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
370    pub struct Request<C>(C);
371
372    impl<C> Request<C>
373    where
374        C: Connection,
375    {
376        pub fn wrap(connection: C) -> Request<C> {
377            if !connection.is_request_initiated() {
378                panic!("connection is not in request phase");
379            }
380
381            Request(connection)
382        }
383
384        pub async fn submit(mut self) -> Result<Response<C>, C::Error> {
385            self.0.initiate_response().await?;
386
387            Ok(Response(self.0))
388        }
389
390        pub fn connection(&mut self) -> &mut C {
391            &mut self.0
392        }
393
394        pub fn release(self) -> C {
395            self.0
396        }
397
398        pub async fn write(&mut self, buf: &[u8]) -> Result<usize, C::Error> {
399            self.0.write(buf).await
400        }
401
402        pub async fn flush(&mut self) -> Result<(), C::Error> {
403            self.0.flush().await
404        }
405    }
406
407    impl<C> ErrorType for Request<C>
408    where
409        C: ErrorType,
410    {
411        type Error = C::Error;
412    }
413
414    impl<C> Write for Request<C>
415    where
416        C: Connection,
417    {
418        async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
419            Request::write(self, buf).await
420        }
421
422        async fn flush(&mut self) -> Result<(), Self::Error> {
423            Request::flush(self).await
424        }
425    }
426
427    #[derive(Debug)]
428    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
429    pub struct Response<C>(C);
430
431    impl<C> Response<C>
432    where
433        C: Connection,
434    {
435        pub fn wrap(connection: C) -> Response<C> {
436            if !connection.is_response_initiated() {
437                panic!("connection is not in response phase");
438            }
439
440            Response(connection)
441        }
442
443        pub fn split(&mut self) -> (&C::Headers, &mut C::Read) {
444            self.0.split()
445        }
446
447        pub fn connection(&mut self) -> &mut C {
448            &mut self.0
449        }
450
451        pub fn release(self) -> C {
452            self.0
453        }
454
455        pub fn status(&self) -> u16 {
456            self.0.status()
457        }
458
459        pub fn status_message(&self) -> Option<&'_ str> {
460            self.0.status_message()
461        }
462
463        pub fn header(&self, name: &str) -> Option<&'_ str> {
464            self.0.header(name)
465        }
466
467        pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, C::Error> {
468            self.0.read(buf).await
469        }
470    }
471
472    impl<C> Status for Response<C>
473    where
474        C: Connection,
475    {
476        fn status(&self) -> u16 {
477            Response::status(self)
478        }
479
480        fn status_message(&self) -> Option<&'_ str> {
481            Response::status_message(self)
482        }
483    }
484
485    impl<C> Headers for Response<C>
486    where
487        C: Connection,
488    {
489        fn header(&self, name: &str) -> Option<&'_ str> {
490            Response::header(self, name)
491        }
492    }
493
494    impl<C> ErrorType for Response<C>
495    where
496        C: ErrorType,
497    {
498        type Error = C::Error;
499    }
500
501    impl<C> Read for Response<C>
502    where
503        C: Connection,
504    {
505        async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
506            Response::read(self, buf).await
507        }
508    }
509
510    pub trait Connection: Status + Headers + Read + Write {
511        type Headers: Status + Headers;
512
513        type Read: Read<Error = Self::Error>;
514
515        type RawConnectionError: Error;
516
517        type RawConnection: Read<Error = Self::RawConnectionError>
518            + Write<Error = Self::RawConnectionError>;
519
520        async fn initiate_request(
521            &mut self,
522            method: Method,
523            uri: &str,
524            headers: &[(&str, &str)],
525        ) -> Result<(), Self::Error>;
526
527        fn is_request_initiated(&self) -> bool;
528
529        async fn initiate_response(&mut self) -> Result<(), Self::Error>;
530
531        fn is_response_initiated(&self) -> bool;
532
533        fn split(&mut self) -> (&Self::Headers, &mut Self::Read);
534
535        fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error>;
536    }
537
538    impl<C> Connection for &mut C
539    where
540        C: Connection,
541    {
542        type Headers = C::Headers;
543
544        type Read = C::Read;
545
546        type RawConnectionError = C::RawConnectionError;
547
548        type RawConnection = C::RawConnection;
549
550        async fn initiate_request(
551            &mut self,
552            method: Method,
553            uri: &str,
554            headers: &[(&str, &str)],
555        ) -> Result<(), Self::Error> {
556            (*self).initiate_request(method, uri, headers).await
557        }
558
559        fn is_request_initiated(&self) -> bool {
560            (**self).is_request_initiated()
561        }
562
563        async fn initiate_response(&mut self) -> Result<(), Self::Error> {
564            (*self).initiate_response().await
565        }
566
567        fn is_response_initiated(&self) -> bool {
568            (**self).is_response_initiated()
569        }
570
571        fn split(&mut self) -> (&Self::Headers, &mut Self::Read) {
572            (*self).split()
573        }
574
575        fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error> {
576            (*self).raw_connection()
577        }
578    }
579}