apns_h2/request/notification/options.rs
1use crate::error::Error;
2use std::fmt;
3
4#[derive(Debug, Clone)]
5pub struct CollapseId<'a> {
6 pub value: &'a str,
7}
8
9/// A collapse-id container. Will not allow bigger id's than 64 bytes.
10impl<'a> CollapseId<'a> {
11 pub fn new(value: &'a str) -> Result<CollapseId<'a>, Error> {
12 if value.len() > 64 {
13 Err(Error::InvalidOptions(String::from(
14 "The collapse-id is too big. Maximum 64 bytes.",
15 )))
16 } else {
17 Ok(CollapseId { value })
18 }
19 }
20}
21
22#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
23/// The apns-push-type header field has the following valid values.
24/// The descriptions below describe when and how to use these values.
25/// Send an apns-push-type header with each push. Recent and upcoming features
26/// may not work if this header is missing. See the table above to determine if
27/// this header is required or optional.
28///
29/// see https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns#4294485
30pub enum PushType {
31 /// The push type for notifications that trigger a user interaction—for example,
32 /// an alert, badge, or sound.
33 #[default]
34 Alert,
35 /// The push type for notifications that deliver content in the background, and
36 /// don’t trigger any user interactions.
37 Background,
38 /// The push type for notifications that request a user’s location.
39 Location,
40 /// The push type for notifications that provide information about an incoming
41 /// Voice-over-IP (VoIP) call.
42 Voip,
43 /// The push type to signal changes to a File Provider extension.
44 FileProvider,
45 /// The push type for notifications that tell managed devices to contact the
46 /// MDM server.
47 Mdm,
48 /// The push type to signal changes to a live activity session.
49 LiveActivity,
50 /// The push type for notifications that provide information about updates to
51 /// your application’s push to talk services.
52 PushToTalk,
53}
54
55impl fmt::Display for PushType {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.write_str(match self {
58 PushType::Alert => "alert",
59 PushType::Background => "background",
60 PushType::Location => "location",
61 PushType::Voip => "voip",
62 PushType::FileProvider => "fileprovider",
63 PushType::Mdm => "mdm",
64 PushType::LiveActivity => "liveactivity",
65 PushType::PushToTalk => "pushtotalk",
66 })
67 }
68}
69
70/// Headers to specify options to the notification.
71#[derive(Debug, Default, Clone)]
72pub struct NotificationOptions<'a> {
73 /// A canonical UUID that identifies the notification. If there is an error
74 /// sending the notification, APNs uses this value to identify the
75 /// notification to your server.
76 pub apns_id: Option<&'a str>,
77
78 /// The apns-push-type header field has the following valid values.
79 ///
80 /// Recent and upcoming features may not work if this header is missing.
81 /// See the table above to determine if this header is required or optional.
82 pub apns_push_type: Option<PushType>,
83
84 /// A UNIX epoch date expressed in seconds (UTC). This header identifies the
85 /// date when the notification is no longer valid and can be discarded.
86 ///
87 /// If this value is nonzero, APNs stores the notification and tries to
88 /// deliver it at least once, repeating the attempt as needed if it is unable
89 /// to deliver the notification the first time. If the value is 0, APNs
90 /// treats the notification as if it expires immediately and does not store
91 /// the notification or attempt to redeliver it.
92 pub apns_expiration: Option<u64>,
93
94 /// The priority of the notification. If `None`, the APNs server sets the priority to High.
95 pub apns_priority: Option<Priority>,
96
97 /// The topic of the remote notification, which is typically the bundle ID
98 /// for your app. The certificate you create in your developer account must
99 /// include the capability for this topic.
100 ///
101 /// If your certificate includes multiple topics, you must specify a value
102 /// for this header.
103 ///
104 /// If you omit this request header and your APNs certificate does not
105 /// specify multiple topics, the APNs server uses the certificate’s Subject
106 /// as the default topic.
107 ///
108 /// If you are using a provider token instead of a certificate, you must
109 /// specify a value for this request header. The topic you provide should be
110 /// provisioned for the your team named in your developer account.
111 pub apns_topic: Option<&'a str>,
112
113 /// Multiple notifications with the same collapse identifier are displayed to the
114 /// user as a single notification. The value of this key must not exceed 64
115 /// bytes.
116 pub apns_collapse_id: Option<CollapseId<'a>>,
117}
118
119/// The importance how fast to bring the notification for the user..
120#[derive(Debug, Clone)]
121pub enum Priority {
122 /// Send the push message immediately. Notifications with this priority must
123 /// trigger an alert, sound, or badge on the target device. Cannot be used
124 /// with the silent notification.
125 High,
126
127 /// Send the push message at a time that takes into account power
128 /// considerations for the device. Notifications with this priority might be
129 /// grouped and delivered in bursts. They are throttled, and in some cases
130 /// are not delivered.
131 Normal,
132}
133
134impl fmt::Display for Priority {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 let priority = match self {
137 Priority::High => "10",
138 Priority::Normal => "5",
139 };
140
141 write!(f, "{}", priority)
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use std::str;
149
150 #[test]
151 fn test_collapse_id_under_64_chars() {
152 let collapse_id = CollapseId::new("foo").unwrap();
153 assert_eq!("foo", collapse_id.value);
154 }
155
156 #[test]
157 fn test_collapse_id_over_64_chars() {
158 let mut long_string = Vec::with_capacity(65);
159 long_string.extend_from_slice(&[65; 65]);
160
161 let collapse_id = CollapseId::new(str::from_utf8(&long_string).unwrap());
162 assert!(collapse_id.is_err());
163 }
164}