walker_common/fetcher/
data.rs

1use bytes::Bytes;
2use reqwest::{Response, StatusCode};
3use serde::de::DeserializeOwned;
4use std::future::Future;
5use std::ops::{Deref, DerefMut};
6
7/// Data which can be extracted from a [`Response`].
8pub trait Data: Sized {
9    fn from_response(response: Response) -> impl Future<Output = Result<Self, reqwest::Error>>;
10}
11
12/// String data
13impl Data for String {
14    async fn from_response(response: Response) -> Result<Self, reqwest::Error> {
15        response.error_for_status()?.text().await
16    }
17}
18
19/// BLOB data
20impl Data for Bytes {
21    async fn from_response(response: Response) -> Result<Self, reqwest::Error> {
22        response.error_for_status()?.bytes().await
23    }
24}
25
26/// A new-type wrapping [`String`].
27pub struct Text(pub String);
28
29impl Data for Text {
30    async fn from_response(response: Response) -> Result<Self, reqwest::Error> {
31        response.error_for_status()?.text().await.map(Self)
32    }
33}
34
35impl Text {
36    pub fn into_inner(self) -> String {
37        self.0
38    }
39}
40
41impl Deref for Text {
42    type Target = String;
43
44    fn deref(&self) -> &Self::Target {
45        &self.0
46    }
47}
48
49impl DerefMut for Text {
50    fn deref_mut(&mut self) -> &mut Self::Target {
51        &mut self.0
52    }
53}
54
55/// JSON based data.
56pub struct Json<D>(pub D)
57where
58    D: DeserializeOwned;
59
60impl<D> Data for Json<D>
61where
62    D: DeserializeOwned,
63{
64    async fn from_response(response: Response) -> Result<Self, reqwest::Error> {
65        response.error_for_status()?.json().await.map(Self)
66    }
67}
68
69impl<D: DeserializeOwned> Json<D> {
70    #[inline]
71    pub fn into_inner(self) -> D {
72        self.0
73    }
74}
75
76impl<D: DeserializeOwned> Deref for Json<D> {
77    type Target = D;
78
79    fn deref(&self) -> &Self::Target {
80        &self.0
81    }
82}
83
84impl<D: DeserializeOwned> DerefMut for Json<D> {
85    fn deref_mut(&mut self) -> &mut Self::Target {
86        &mut self.0
87    }
88}
89
90impl<D: Data> Data for Option<D> {
91    async fn from_response(response: Response) -> Result<Self, reqwest::Error> {
92        if response.status() == StatusCode::NOT_FOUND {
93            return Ok(None);
94        }
95
96        Ok(Some(D::from_response(response).await?))
97    }
98}