Skip to main content

onesignal_rust_api/apis/
mod.rs

1use std::error;
2use std::fmt;
3
4#[derive(Debug, Clone)]
5pub struct ResponseContent<T> {
6    pub status: reqwest::StatusCode,
7    pub content: String,
8    pub entity: Option<T>,
9}
10
11#[derive(Debug)]
12pub enum Error<T> {
13    Reqwest(reqwest::Error),
14    Serde(serde_json::Error),
15    Io(std::io::Error),
16    ResponseError(ResponseContent<T>),
17}
18
19impl <T> Error<T> {
20    /// The error messages carried by the response body, normalized to a flat
21    /// `Vec<String>` regardless of which envelope shape the API returned
22    /// (`{"errors": "..."}`, `{"errors": ["..."]}`,
23    /// `{"errors": [{"code": ..., "title": ...}]}`, or an object map such as
24    /// `{"errors": {"invalid_aliases": {...}}}`, surfaced as `"<key>: <value>"`
25    /// entries). Returns an empty `Vec` for non-response errors (network, serde,
26    /// IO) or when the body is not a recognizable error envelope. The raw
27    /// response remains available on the `ResponseError` variant.
28    pub fn error_messages(&self) -> Vec<String> {
29        let content = match self {
30            Error::ResponseError(response) => &response.content,
31            _ => return Vec::new(),
32        };
33
34        let parsed: serde_json::Value = match serde_json::from_str(content) {
35            Ok(value) => value,
36            Err(_) => return Vec::new(),
37        };
38
39        match parsed.get("errors") {
40            Some(serde_json::Value::String(message)) => vec![message.clone()],
41            Some(serde_json::Value::Array(items)) => items
42                .iter()
43                .filter_map(|item| match item {
44                    serde_json::Value::String(message) => Some(message.clone()),
45                    serde_json::Value::Object(object) => object
46                        .get("title")
47                        .filter(|value| !value.is_null() && value.as_str() != Some(""))
48                        .or_else(|| object.get("code"))
49                        .and_then(|value| match value {
50                            serde_json::Value::String(message) => Some(message.clone()),
51                            serde_json::Value::Null => None,
52                            other => Some(other.to_string()),
53                        }),
54                    _ => None,
55                })
56                .collect(),
57            Some(serde_json::Value::Object(map)) => {
58                // Object-shaped envelopes (e.g. {"invalid_aliases": {...}}) carry
59                // data under arbitrary keys; surface each so it isn't silently
60                // dropped. Key order is unspecified, so sort for deterministic output.
61                let mut messages: Vec<String> = map
62                    .iter()
63                    .map(|(key, value)| match value {
64                        serde_json::Value::String(message) => format!("{}: {}", key, message),
65                        other => format!("{}: {}", key, other),
66                    })
67                    .collect();
68                messages.sort();
69                messages
70            }
71            _ => Vec::new(),
72        }
73    }
74}
75
76impl <T> fmt::Display for Error<T> {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        let (module, e) = match self {
79            Error::Reqwest(e) => ("reqwest", e.to_string()),
80            Error::Serde(e) => ("serde", e.to_string()),
81            Error::Io(e) => ("IO", e.to_string()),
82            Error::ResponseError(e) => ("response", format!("status code {}", e.status)),
83        };
84        write!(f, "error in {}: {}", module, e)
85    }
86}
87
88impl <T: fmt::Debug> error::Error for Error<T> {
89    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
90        Some(match self {
91            Error::Reqwest(e) => e,
92            Error::Serde(e) => e,
93            Error::Io(e) => e,
94            Error::ResponseError(_) => return None,
95        })
96    }
97}
98
99impl <T> From<reqwest::Error> for Error<T> {
100    fn from(e: reqwest::Error) -> Self {
101        Error::Reqwest(e)
102    }
103}
104
105impl <T> From<serde_json::Error> for Error<T> {
106    fn from(e: serde_json::Error) -> Self {
107        Error::Serde(e)
108    }
109}
110
111impl <T> From<std::io::Error> for Error<T> {
112    fn from(e: std::io::Error) -> Self {
113        Error::Io(e)
114    }
115}
116
117pub fn urlencode<T: AsRef<str>>(s: T) -> String {
118    ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect()
119}
120
121pub mod default_api;
122
123pub mod configuration;