Skip to main content

bark_apns/
error.rs

1/// Result type used by this crate.
2///
3/// The default error type is [`Error`], but the alias accepts a custom error
4/// parameter when needed.
5pub type Result<T, E = Error> = std::result::Result<T, E>;
6
7/// Error type for Bark APNs operations.
8///
9/// The enum is non-exhaustive so the crate can add more precise variants later
10/// without breaking downstream code. Applications can convert it into
11/// `anyhow::Error` with `?`, while libraries can match individual variants.
12#[non_exhaustive]
13#[derive(Debug, thiserror::Error)]
14pub enum Error {
15    /// The encryption key length does not match the selected AES algorithm.
16    #[error(
17        "invalid encryption key length for {algorithm}: expected {expected} bytes, got {actual}"
18    )]
19    InvalidKeyLength {
20        /// Bark algorithm name, such as `AES128`.
21        algorithm: &'static str,
22        /// Expected UTF-8 byte length.
23        expected: usize,
24        /// Actual UTF-8 byte length.
25        actual: usize,
26    },
27
28    /// The IV length does not match the selected AES mode.
29    #[error("invalid IV length for {mode}: expected {expected} bytes, got {actual}")]
30    InvalidIvLength {
31        /// Bark mode name, such as `CBC`.
32        mode: &'static str,
33        /// Expected UTF-8 byte length.
34        expected: usize,
35        /// Actual UTF-8 byte length.
36        actual: usize,
37    },
38
39    /// The message id is too long to be used as an APNs collapse id.
40    #[error("invalid APNs collapse id: expected at most 64 bytes, got {actual}")]
41    InvalidCollapseId {
42        /// Actual UTF-8 byte length.
43        actual: usize,
44    },
45
46    /// A delete message was serialized or sent without an id.
47    #[error("delete messages require an id")]
48    MissingMessageIdForDelete,
49
50    /// A normal non-delete message has neither body nor markdown.
51    #[error("message body or markdown is required")]
52    EmptyMessage,
53
54    /// A value could not be encoded as an APNs HTTP header.
55    #[error("invalid APNs header value for {name}: {source}")]
56    InvalidHeaderValue {
57        /// Header name being constructed.
58        name: &'static str,
59        /// Underlying header parsing error.
60        #[source]
61        source: reqwest::header::InvalidHeaderValue,
62    },
63
64    /// The HTTP client could not be constructed.
65    #[error("failed to build HTTP client: {0}")]
66    HttpClient(#[source] reqwest::Error),
67
68    /// An HTTP request failed before receiving a per-device APNs response.
69    #[error("APNs request failed: {0}")]
70    Http(#[from] reqwest::Error),
71
72    /// APNs provider-token generation failed.
73    #[error("APNs token generation failed: {0}")]
74    Jwt(#[from] jsonwebtoken::errors::Error),
75
76    /// JSON serialization failed.
77    #[error("failed to serialize payload: {0}")]
78    Json(#[from] serde_json::Error),
79
80    /// Encryption failed after input validation.
81    #[error("encryption failed")]
82    Encryption,
83
84    /// Random IV generation failed.
85    #[error("failed to generate random IV: {0}")]
86    Random(
87        /// Randomness provider error text.
88        String,
89    ),
90
91    /// One or more device tokens failed during a multi-device send.
92    #[error("APNs failed for one or more devices: {0}")]
93    ApnsFailures(
94        /// Human-readable summary containing failed device tokens and reasons.
95        String,
96    ),
97}
98
99impl From<getrandom::Error> for Error {
100    fn from(error: getrandom::Error) -> Self {
101        Self::Random(error.to_string())
102    }
103}