headless_common/api/
mod.rs

1use std::error;
2use std::fmt;
3
4pub mod field_collection;
5pub mod filter;
6pub mod page_params;
7pub mod sort;
8
9#[derive(Debug, Clone)]
10pub struct ResponseContent<T> {
11    pub status: reqwest::StatusCode,
12    pub content: String,
13    pub entity: Option<T>,
14}
15
16#[derive(Debug)]
17pub enum Error<T> {
18    Reqwest(reqwest::Error),
19    Serde(serde_json::Error),
20    Io(std::io::Error),
21    ResponseError(ResponseContent<T>),
22}
23
24impl<T> fmt::Display for Error<T> {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        let (module, e) = match self {
27            Error::Reqwest(e) => ("reqwest", e.to_string()),
28            Error::Serde(e) => ("serde", e.to_string()),
29            Error::Io(e) => ("IO", e.to_string()),
30            Error::ResponseError(e) => ("response", format!("status code {}", e.status)),
31        };
32        write!(f, "error in {module}: {e}")
33    }
34}
35
36impl<T: fmt::Debug> error::Error for Error<T> {
37    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
38        Some(match self {
39            Error::Reqwest(e) => e,
40            Error::Serde(e) => e,
41            Error::Io(e) => e,
42            Error::ResponseError(_) => return None,
43        })
44    }
45}
46
47impl<T> From<reqwest::Error> for Error<T> {
48    fn from(e: reqwest::Error) -> Self {
49        Error::Reqwest(e)
50    }
51}
52
53impl<T> From<serde_json::Error> for Error<T> {
54    fn from(e: serde_json::Error) -> Self {
55        Error::Serde(e)
56    }
57}
58
59impl<T> From<std::io::Error> for Error<T> {
60    fn from(e: std::io::Error) -> Self {
61        Error::Io(e)
62    }
63}
64
65pub fn urlencode<T: AsRef<str>>(s: T) -> String {
66    ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect()
67}
68
69pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> {
70    if let serde_json::Value::Object(object) = value {
71        let mut params = vec![];
72
73        for (key, value) in object {
74            match value {
75                serde_json::Value::Object(_) => {
76                    params.append(&mut parse_deep_object(&format!("{prefix}[{key}]"), value))
77                }
78                serde_json::Value::Array(array) => {
79                    for (i, value) in array.iter().enumerate() {
80                        params.append(&mut parse_deep_object(
81                            &format!("{prefix}[{key}][{i}]"),
82                            value,
83                        ));
84                    }
85                }
86                serde_json::Value::String(s) => {
87                    params.push((format!("{prefix}[{key}]"), s.clone()))
88                }
89                _ => params.push((format!("{prefix}[{key}]"), value.to_string())),
90            }
91        }
92
93        return params;
94    }
95
96    unimplemented!("Only objects are supported with style=deepObject")
97}