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}