Skip to main content

fcm_device_group/
error.rs

1//! Errors returns by the FCM device group APIs
2//!
3use std::fmt::Display;
4
5use reqwest::{StatusCode, header::InvalidHeaderValue};
6use serde::{Deserialize, de::DeserializeOwned};
7use thiserror::Error;
8
9/// Error when creating FCM Device Groups Client
10#[derive(Debug, Error)]
11pub enum FCMDeviceGroupClientCreationError {
12    #[allow(missing_docs)]
13    #[error("Error Making Authorization Header")]
14    InvalidHeaderValue(#[from] InvalidHeaderValue),
15    #[allow(missing_docs)]
16    #[error("Build Client Error")]
17    ClientBuild(#[from] reqwest::Error),
18}
19
20#[allow(missing_docs)]
21pub trait FCMDeviceGroupError: std::error::Error + Sized {
22    fn from_error_str(error: FCMDeviceGroupsBadRequest) -> Option<Self>;
23}
24
25/// Error When Making an FCM Device Groups Request
26///
27/// E is a generic parameter for a request specific error
28#[derive(Debug, Error)]
29pub enum FCMDeviceGroupsRequestError<E: FCMDeviceGroupError> {
30    /// Error http error
31    #[error("Error Making HTTP Request with FCM")]
32    HttpError(#[from] reqwest::Error),
33    /// Get Token Error
34    #[error("Error Getting Auth Token")]
35    GetTokenError(Box<dyn std::error::Error + Send + Sync>),
36    /// Parsed Bad Request Error
37    #[error("Bad Request")]
38    BadRequestError(#[from] E),
39}
40
41impl<E: FCMDeviceGroupError> FCMDeviceGroupsRequestError<E> {
42    pub(crate) async fn json_response<T: DeserializeOwned>(
43        resp: reqwest::Response,
44    ) -> Result<T, Self> {
45        match resp.error_for_status_ref() {
46            Ok(_) => Ok(resp.json::<T>().await?),
47            Err(e) => match e.status().unwrap() {
48                StatusCode::BAD_REQUEST => {
49                    let string_error = resp.json::<FCMDeviceGroupsBadRequest>().await?;
50                    Err(match E::from_error_str(string_error) {
51                        Some(custom_error) => Self::BadRequestError(custom_error),
52                        None => Self::HttpError(e),
53                    })
54                }
55                _ => Err(Self::HttpError(e)),
56            },
57        }
58    }
59}
60
61/// Bad Request Error from FCM
62#[derive(Debug, Deserialize, Error)]
63pub struct FCMDeviceGroupsBadRequest {
64    /// Bad request message body from fcm
65    pub error: String,
66}
67
68impl FCMDeviceGroupError for FCMDeviceGroupsBadRequest {
69    fn from_error_str(error: FCMDeviceGroupsBadRequest) -> Option<Self> {
70        Some(error)
71    }
72}
73
74impl Display for FCMDeviceGroupsBadRequest {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(f, "{}", self.error)
77    }
78}
79
80#[allow(missing_docs)]
81pub mod operation_errors {
82    //! Operation Specific Errors
83
84    use thiserror::Error;
85
86    use crate::error::FCMDeviceGroupError;
87
88    const ALREADY_EXISTS_MESSAGE: &str = "notification_key already exists";
89    const NO_REGISTRATION_ID_MESSAGE: &str = "no valid registration ids";
90    const KEY_NAME_AND_KEY_DONT_MATCH: &str =
91        "notification_key_name doesn't match the group name of the notification_key";
92    const KEY_NOT_FOUND: &str = "notification_key not found";
93
94    pub type OperationResult<T, E> = Result<T, super::FCMDeviceGroupsRequestError<E>>;
95
96    #[derive(Debug, Error)]
97    pub enum CreateGroupError {
98        #[error("{}", ALREADY_EXISTS_MESSAGE)]
99        AlreadyExists,
100        #[error("{}", NO_REGISTRATION_ID_MESSAGE)]
101        NoValidRegistrationIds,
102    }
103
104    impl FCMDeviceGroupError for CreateGroupError {
105        fn from_error_str(error: super::FCMDeviceGroupsBadRequest) -> Option<Self> {
106            match error.error.as_str() {
107                ALREADY_EXISTS_MESSAGE => Some(Self::AlreadyExists),
108                NO_REGISTRATION_ID_MESSAGE => Some(Self::NoValidRegistrationIds),
109                _ => None,
110            }
111        }
112    }
113
114    #[derive(Debug, Error)]
115    pub enum ChangeGroupMembersError {
116        #[error("{}", NO_REGISTRATION_ID_MESSAGE)]
117        NoValidRegistrationIds,
118        #[error("{KEY_NAME_AND_KEY_DONT_MATCH}")]
119        KeyNameAndKeyDontMatch,
120        #[error("{KEY_NOT_FOUND}")]
121        KeyNotFound,
122    }
123
124    impl FCMDeviceGroupError for ChangeGroupMembersError {
125        fn from_error_str(error: super::FCMDeviceGroupsBadRequest) -> Option<Self> {
126            match error.error.as_str() {
127                NO_REGISTRATION_ID_MESSAGE => Some(Self::NoValidRegistrationIds),
128                KEY_NAME_AND_KEY_DONT_MATCH => Some(Self::KeyNameAndKeyDontMatch),
129                KEY_NOT_FOUND => Some(Self::KeyNotFound),
130                _ => None,
131            }
132        }
133    }
134
135    #[derive(Debug, Error)]
136    pub enum GetKeyError {
137        #[error("{KEY_NOT_FOUND}")]
138        KeyNotFound,
139    }
140    impl FCMDeviceGroupError for GetKeyError {
141        fn from_error_str(error: super::FCMDeviceGroupsBadRequest) -> Option<Self> {
142            match error.error.as_str() {
143                KEY_NOT_FOUND => Some(Self::KeyNotFound),
144                _ => None,
145            }
146        }
147    }
148}
149
150#[derive(Debug, Error)]
151pub(crate) enum RawError {
152    #[error("Error Making HTTP Request with FCM")]
153    HttpError(#[from] reqwest::Error),
154    /// Get Token Error
155    #[error("Error Getting Auth Token")]
156    GetTokenError(Box<dyn std::error::Error + Send + Sync>),
157}
158
159impl<E: FCMDeviceGroupError> From<RawError> for FCMDeviceGroupsRequestError<E> {
160    fn from(raw: RawError) -> Self {
161        match raw {
162            RawError::HttpError(error) => Self::HttpError(error),
163            RawError::GetTokenError(error) => Self::GetTokenError(error),
164        }
165    }
166}