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 message id is too long to be used as an APNs collapse id.
29    #[error("invalid APNs collapse id: expected at most 64 bytes, got {actual}")]
30    InvalidCollapseId {
31        /// Actual UTF-8 byte length.
32        actual: usize,
33    },
34
35    /// A delete message was serialized or sent without an id.
36    #[error("delete messages require an id")]
37    MissingMessageIdForDelete,
38
39    /// A normal non-delete message has neither body nor markdown.
40    #[error("message body or markdown is required")]
41    EmptyMessage,
42
43    /// An encrypted message was sent to a device without encryption settings.
44    #[error("encrypted messages require encryption settings for device {device}")]
45    MissingDeviceEncryption {
46        /// Normalized iOS device token.
47        device: String,
48    },
49
50    /// A value could not be encoded as an APNs HTTP header.
51    #[error("invalid APNs header value for {name}: {source}")]
52    InvalidHeaderValue {
53        /// Header name being constructed.
54        name: &'static str,
55        /// Underlying header parsing error.
56        #[source]
57        source: reqwest::header::InvalidHeaderValue,
58    },
59
60    /// The HTTP client could not be constructed.
61    #[error("failed to build HTTP client: {0}")]
62    HttpClient(#[source] reqwest::Error),
63
64    /// An HTTP request failed before receiving a per-device APNs response.
65    #[error("APNs request failed: {0}")]
66    Http(#[from] reqwest::Error),
67
68    /// APNs provider-token generation failed.
69    #[error("APNs token generation failed: {0}")]
70    Jwt(#[from] jsonwebtoken::errors::Error),
71
72    /// JSON serialization failed.
73    #[error("failed to serialize payload: {0}")]
74    Json(#[from] serde_json::Error),
75
76    /// Encryption failed after input validation.
77    #[error("encryption failed")]
78    Encryption,
79
80    /// Random IV generation failed.
81    #[error("failed to generate random IV: {0}")]
82    Random(
83        /// Randomness provider error text.
84        String,
85    ),
86
87    /// One or more device tokens failed during a multi-device send.
88    #[error("APNs failed for one or more devices: {0}")]
89    ApnsFailures(
90        /// Human-readable summary containing failed device tokens and reasons.
91        String,
92    ),
93}
94
95impl From<getrandom::Error> for Error {
96    fn from(error: getrandom::Error) -> Self {
97        Self::Random(error.to_string())
98    }
99}