mastodon_async/helpers/
log.rs

1use serde::{Deserialize, Serialize};
2
3/// Log metadata about this request based on the type given:
4///
5/// ```no_run
6/// use mastodon_async::log_serde;
7/// tokio_test::block_on(async {
8///   let request = reqwest::get("https://example.org/").await.unwrap();
9///   log::warn!(
10///     status = log_serde!(request Status),
11///     headers = log_serde!(request Headers);
12///     "test"
13///   );
14/// })
15/// ```
16#[macro_export]
17macro_rules! log_serde {
18    ($response:ident $type_name:tt) => {
19        log::as_serde!($crate::helpers::log::$type_name::from(&$response))
20    };
21}
22
23/// Serializable form of reqwest's Status type.
24#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
25pub struct Status {
26    /// The numerical representation of the status
27    pub code: u16,
28    /// it's canonical reason.
29    pub message: Option<&'static str>,
30}
31
32impl Status {
33    /// New from reqwest's Status type (which is more useful but not
34    /// serializable).
35    pub fn new(status: reqwest::StatusCode) -> Self {
36        Self {
37            code: status.as_u16(),
38            message: status.canonical_reason(),
39        }
40    }
41}
42
43impl From<&reqwest::Response> for Status {
44    fn from(value: &reqwest::Response) -> Self {
45        Self::new(value.status())
46    }
47}
48
49/// Helper for logging request headers
50#[derive(Debug)]
51pub struct Headers<'h>(pub &'h reqwest::header::HeaderMap);
52
53impl<'h> Serialize for Headers<'h> {
54    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55    where
56        S: serde::Serializer,
57    {
58        serializer.collect_map(
59            self.0
60                .iter()
61                .map(|(k, v)| (format!("{k:?}"), format!("{v:?}"))),
62        )
63    }
64}
65
66impl<'h> From<&'h reqwest::Response> for Headers<'h> {
67    fn from(value: &'h reqwest::Response) -> Self {
68        Headers(value.headers())
69    }
70}