Change syntax to 2018 edition

This commit is contained in:
Julius de Bruijn
2018-11-01 13:30:58 +01:00
parent a948070142
commit 470943fffc
16 changed files with 118 additions and 161 deletions
+1
View File
@@ -12,6 +12,7 @@ keywords = ["apns", "apple", "push", "async", "http2"]
repository = "https://github.com/pimeys/a2.git"
homepage = "https://github.com/pimeys/a2"
documentation = "https://pimeys.github.io/a2/"
edition = "2018"
[dependencies]
serde = "1.0"
+1 -9
View File
@@ -30,19 +30,11 @@ Add this to `Cargo.toml`:
```
[dependencies]
a2 = "0.3"
a2 = "0.4"
tokio = "0.1"
futures = "0.1"
```
then add to your crate root:
```rust
extern crate a2;
extern crate tokio;
extern crate futures;
```
## Examples
The library supports connecting to Apple Push Notification service [either using
+2 -6
View File
@@ -1,9 +1,5 @@
extern crate a2;
extern crate argparse;
extern crate tokio;
extern crate pretty_env_logger;
extern crate futures;
use tokio;
use pretty_env_logger;
use argparse::{ArgumentParser, Store, StoreOption, StoreTrue};
use std::fs::File;
use a2::{
+3 -8
View File
@@ -1,10 +1,7 @@
extern crate a2;
extern crate argparse;
extern crate tokio;
extern crate pretty_env_logger;
extern crate futures;
use tokio;
use pretty_env_logger;
use argparse::{ArgumentParser, Store, StoreOption, StoreTrue};
use std::fs::File;
use a2::{
Client,
@@ -19,8 +16,6 @@ use futures::{
Future,
};
use std::fs::File;
// An example client connectiong to APNs with a JWT token
fn main() {
pretty_env_logger::init();
+15 -15
View File
@@ -1,9 +1,9 @@
//! The client module for sending requests and parsing responses
use signer::Signer;
use crate::signer::Signer;
use hyper_alpn::AlpnConnector;
use error::Error;
use error::Error::ResponseError;
use crate::error::Error;
use crate::error::Error::ResponseError;
use futures::{
Future,
@@ -20,8 +20,8 @@ use hyper::{
};
use http::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE};
use request::payload::Payload;
use response::Response;
use crate::request::payload::Payload;
use crate::response::Response;
use serde_json;
use std::{fmt, str};
use std::time::Duration;
@@ -39,10 +39,10 @@ pub enum Endpoint {
}
impl fmt::Display for Endpoint {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let host = match self {
&Endpoint::Production => "api.push.apple.com",
&Endpoint::Sandbox => "api.development.push.apple.com",
Endpoint::Production => "api.push.apple.com",
Endpoint::Sandbox => "api.development.push.apple.com",
};
write!(f, "{}", host)
@@ -224,7 +224,7 @@ impl Client {
})
}
fn build_request(&self, payload: Payload) -> hyper::Request<Body> {
fn build_request(&self, payload: Payload<'_>) -> hyper::Request<Body> {
let path = format!(
"https://{}/3/device/{}",
self.endpoint, payload.device_token
@@ -263,10 +263,10 @@ impl Client {
}
}
pub struct FutureResponse(Box<Future<Item = Response, Error = Error> + Send + 'static>);
pub struct FutureResponse(Box<dyn Future<Item = Response, Error = Error> + Send + 'static>);
impl fmt::Debug for FutureResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Future<Response>")
}
}
@@ -283,13 +283,13 @@ impl Future for FutureResponse {
#[cfg(test)]
mod tests {
use super::*;
use request::notification::PlainNotificationBuilder;
use request::notification::NotificationBuilder;
use request::notification::{NotificationOptions, Priority, CollapseId};
use crate::request::notification::PlainNotificationBuilder;
use crate::request::notification::NotificationBuilder;
use crate::request::notification::{NotificationOptions, Priority, CollapseId};
use hyper_alpn::AlpnConnector;
use hyper::Method;
use http::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE};
use signer::Signer;
use crate::signer::Signer;
const PRIVATE_KEY: &'static str = indoc!(
"-----BEGIN PRIVATE KEY-----
+20 -13
View File
@@ -1,6 +1,6 @@
//! Error and result module
use client::FutureResponse;
use crate::client::FutureResponse;
use tokio_timer::TimeoutError;
use std::error::Error as StdError;
use std::io::Error as IoError;
@@ -8,36 +8,43 @@ use serde_json::Error as SerdeError;
use openssl::error::ErrorStack;
use std::fmt;
use std::convert::From;
use response::{Response, ErrorBody};
use crate::response::{Response, ErrorBody};
#[derive(Debug)]
pub enum Error {
/// User request or Apple response JSON data was faulty.
SerializeError,
/// A problem connecting to APNs servers.
ConnectionError,
/// APNs couldn't response in a timely manner, if using
/// [send_with_timeout](client/struct.Client.html#method.send_with_timeout)
TimeoutError,
/// Couldn't generate an APNs token with the given key.
SignerError(String),
/// APNs couldn't accept the notification. Contains
/// [Response](response/struct.Response.html) with additional
/// information.
ResponseError(Response),
/// Invalid option values given in
/// [NotificationOptions](request/notification/struct.NotificationOptions.html)
InvalidOptions(String),
/// TLS connection failed
TlsError(String),
/// Error reading the certificate or private key.
ReadError(String),
}
impl<'a> fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
&Error::ResponseError(Response { error: Some(ErrorBody { ref reason, .. }), .. }) => {
Error::ResponseError(Response { error: Some(ErrorBody { ref reason, .. }), .. }) => {
write!(fmt, "{} (reason: {:?})", self.description(), reason)
},
_ => write!(fmt, "{}", self.description()),
@@ -48,18 +55,18 @@ impl<'a> fmt::Display for Error {
impl<'a> StdError for Error {
fn description(&self) -> &str {
match self {
&Error::SerializeError => "Error serializing to JSON",
&Error::ConnectionError => "Error connecting to APNs",
&Error::SignerError(_) => "Error creating a signature",
&Error::ResponseError(_) => "Notification was not accepted by APNs",
&Error::InvalidOptions(_) => "Invalid options for APNs payload",
&Error::TlsError(_) => "Error in creating a TLS connection",
&Error::ReadError(_) => "Error in reading a certificate file",
&Error::TimeoutError => "Timeout in sending a push notification",
Error::SerializeError => "Error serializing to JSON",
Error::ConnectionError => "Error connecting to APNs",
Error::SignerError(_) => "Error creating a signature",
Error::ResponseError(_) => "Notification was not accepted by APNs",
Error::InvalidOptions(_) => "Invalid options for APNs payload",
Error::TlsError(_) => "Error in creating a TLS connection",
Error::ReadError(_) => "Error in reading a certificate file",
Error::TimeoutError => "Timeout in sending a push notification",
}
}
fn cause(&self) -> Option<&StdError> {
fn cause(&self) -> Option<&dyn StdError> {
None
}
}
+4 -27
View File
@@ -37,10 +37,6 @@
//! ## Example sending a plain notification using token authentication:
//!
//! ```no_run
//! extern crate tokio;
//! extern crate a2;
//! extern crate futures;
//!
//! use a2::{PlainNotificationBuilder, NotificationBuilder, Client, Endpoint};
//! use std::fs::File;
//! use futures::future::lazy;
@@ -78,10 +74,6 @@
//!
//! ```no_run
//! #[macro_use] extern crate serde_derive;
//! extern crate serde;
//! extern crate tokio;
//! extern crate a2;
//! extern crate futures;
//!
//! use a2::{Client, Endpoint, SilentNotificationBuilder, NotificationBuilder};
//! use std::fs::File;
@@ -139,28 +131,13 @@ extern crate indoc;
#[macro_use]
extern crate log;
extern crate base64;
extern crate chrono;
extern crate crossbeam;
extern crate erased_serde;
extern crate futures;
extern crate hyper;
extern crate hyper_alpn;
extern crate openssl;
extern crate serde;
extern crate http;
extern crate time;
extern crate tokio;
extern crate tokio_io;
extern crate tokio_timer;
pub mod request;
pub mod error;
pub mod response;
pub mod client;
mod signer;
pub use request::{
pub use crate::request::{
notification::{
NotificationBuilder,
LocalizedNotificationBuilder,
@@ -172,16 +149,16 @@ pub use request::{
}
};
pub use response::{
pub use crate::response::{
Response,
ErrorBody,
ErrorReason,
};
pub use client::{
pub use crate::client::{
Endpoint,
Client,
FutureResponse,
};
pub use error::Error;
pub use crate::error::Error;
@@ -10,7 +10,7 @@ pub use self::plain::PlainNotificationBuilder;
pub use self::silent::SilentNotificationBuilder;
pub use self::options::{CollapseId, NotificationOptions, Priority};
use request::payload::Payload;
use crate::request::payload::Payload;
pub trait NotificationBuilder<'a> {
/// Generates the request payload to be send with the `Client`.
+2 -25
View File
@@ -1,5 +1,5 @@
use request::notification::{NotificationBuilder, NotificationOptions};
use request::payload::{APSAlert, Payload, APS};
use crate::request::notification::{NotificationBuilder, NotificationOptions};
use crate::request::payload::{APSAlert, Payload, APS};
use std::{
collections::BTreeMap,
@@ -36,7 +36,6 @@ pub struct LocalizedAlert<'a> {
/// # Example
///
/// ```rust
/// # extern crate a2;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("Hi there", "What's up?");
@@ -67,8 +66,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// Creates a new builder with the minimum amount of content.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let payload = LocalizedNotificationBuilder::new("a title", "a body")
@@ -106,8 +103,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// A number to show on a badge on top of the app icon.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -129,8 +124,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// File name of the custom sound to play when receiving the notification.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -153,8 +146,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// actions for that category as buttons in the banner or alert interface.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -176,8 +167,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// The localization key for the notification title.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -199,8 +188,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// Arguments for the title localization.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -232,8 +219,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// The localization key for the action.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -255,8 +240,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// The localization key for the push message body.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -278,8 +261,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// Arguments for the content localization.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -311,8 +292,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// Image to display in the rich notification.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
@@ -334,8 +313,6 @@ impl<'a> LocalizedNotificationBuilder<'a> {
/// Allow client to modify push content before displaying.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{LocalizedNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = LocalizedNotificationBuilder::new("a title", "a body");
+4 -4
View File
@@ -1,4 +1,4 @@
use error::Error;
use crate::error::Error;
use std::fmt;
#[derive(Debug, Clone)]
@@ -90,10 +90,10 @@ pub enum Priority {
}
impl fmt::Display for Priority {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let priority = match self {
&Priority::High => "10",
&Priority::Normal => "5",
Priority::High => "10",
Priority::Normal => "5",
};
write!(f, "{}", priority)
+2 -11
View File
@@ -1,5 +1,5 @@
use request::notification::{NotificationBuilder, NotificationOptions};
use request::payload::{APSAlert, Payload, APS};
use crate::request::notification::{NotificationBuilder, NotificationOptions};
use crate::request::payload::{APSAlert, Payload, APS};
use std::collections::BTreeMap;
/// A builder to create a simple APNs notification payload.
@@ -7,7 +7,6 @@ use std::collections::BTreeMap;
/// # Example
///
/// ```rust
/// # extern crate a2;
/// # use a2::request::notification::{NotificationBuilder, PlainNotificationBuilder};
/// # fn main() {
/// let mut builder = PlainNotificationBuilder::new("Hi there");
@@ -29,8 +28,6 @@ impl<'a> PlainNotificationBuilder<'a> {
/// Creates a new builder with the minimum amount of content.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{PlainNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let payload = PlainNotificationBuilder::new("a body")
@@ -55,8 +52,6 @@ impl<'a> PlainNotificationBuilder<'a> {
/// A number to show on a badge on top of the app icon.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{PlainNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = PlainNotificationBuilder::new("a body");
@@ -78,8 +73,6 @@ impl<'a> PlainNotificationBuilder<'a> {
/// File name of the custom sound to play when receiving the notification.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{PlainNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = PlainNotificationBuilder::new("a body");
@@ -102,8 +95,6 @@ impl<'a> PlainNotificationBuilder<'a> {
/// actions for that category as buttons in the banner or alert interface.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{PlainNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let mut builder = PlainNotificationBuilder::new("a body");
+2 -5
View File
@@ -1,5 +1,5 @@
use request::notification::{NotificationBuilder, NotificationOptions};
use request::payload::{Payload, APS};
use crate::request::notification::{NotificationBuilder, NotificationOptions};
use crate::request::payload::{Payload, APS};
use std::collections::BTreeMap;
/// A builder to create an APNs silent notification payload which can be used to
@@ -9,7 +9,6 @@ use std::collections::BTreeMap;
/// # Example
///
/// ```rust
/// # extern crate a2;
/// # use std::collections::HashMap;
/// # use a2::request::notification::{NotificationBuilder, SilentNotificationBuilder};
/// # fn main() {
@@ -35,8 +34,6 @@ impl SilentNotificationBuilder {
/// Creates a new builder.
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{SilentNotificationBuilder, NotificationBuilder};
/// # fn main() {
/// let payload = SilentNotificationBuilder::new()
+3 -7
View File
@@ -1,7 +1,7 @@
//! Payload with `aps` and custom data
use request::notification::{LocalizedAlert, NotificationOptions};
use error::Error;
use crate::request::notification::{LocalizedAlert, NotificationOptions};
use crate::error::Error;
use serde_json::{self, Value};
use std::collections::BTreeMap;
use erased_serde::Serialize;
@@ -30,8 +30,6 @@ impl<'a> Payload<'a> {
/// Using a `HashMap`:
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # use a2::request::notification::{SilentNotificationBuilder, NotificationBuilder};
/// # use std::collections::HashMap;
/// # fn main() {
@@ -52,8 +50,6 @@ impl<'a> Payload<'a> {
/// Using a custom struct:
///
/// ```rust
/// # extern crate a2;
/// # extern crate serde;
/// # #[macro_use] extern crate serde_derive;
/// # use a2::request::notification::{SilentNotificationBuilder, NotificationBuilder};
/// # fn main() {
@@ -76,7 +72,7 @@ impl<'a> Payload<'a> {
pub fn add_custom_data(
&mut self,
root_key: &'a str,
data: &Serialize,
data: &dyn Serialize,
) -> Result<&mut Self, Error>
where
{
+57 -29
View File
@@ -136,36 +136,64 @@ pub enum ErrorReason {
}
impl fmt::Display for ErrorReason {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match *self {
ErrorReason::BadCollapseId => "The collapse identifier exceeds the maximum allowed size.",
ErrorReason::BadDeviceToken => "The specified device token was bad. Verify that the request contains a valid token and that the token matches the environment.",
ErrorReason::BadExpirationDate => "The `apns_expiration` in `NotificationOptions` is bad.",
ErrorReason::BadMessageId => "The `apns_id` in `NotificationOptions` is bad.",
ErrorReason::BadPriority => "The `apns_priority` in `NotificationOptions` is bad.",
ErrorReason::BadTopic => "The `apns_topic` in `NotificationOptions` is bad.",
ErrorReason::DeviceTokenNotForTopic => "The device token does not match the specified topic.",
ErrorReason::DuplicateHeaders => "One or more headers were repeated.",
ErrorReason::IdleTimeout => "Idle time out.",
ErrorReason::MissingDeviceToken => "The device token is not specified in the payload.",
ErrorReason::MissingTopic => "The `apns_topic` of the `NotificationOptions` was not specified and was required. The `apns_topic` header is mandatory when the client is connected using the `CertificateConnector` and the included PKCS12 file includes multiple topics, or when using the `TokenConnector`.",
ErrorReason::PayloadEmpty => "The message payload was empty.",
ErrorReason::TopicDisallowed => "Pushing to this topic is not allowed.",
ErrorReason::BadCertificate => "The certificate was bad.",
ErrorReason::BadCertificateEnvironment => "The client certificate was for the wrong environment.",
ErrorReason::ExpiredProviderToken => "The provider token is stale and a new token should be generated.",
ErrorReason::Forbidden => "The specified action is not allowed.",
ErrorReason::InvalidProviderToken => "The provider token is not valid or the token signature could not be verified.",
ErrorReason::MissingProviderToken => "No provider certificate was used to connect to APNs and Authorization header was missing or no provider token was specified.",
ErrorReason::BadPath => "The request path value is bad.",
ErrorReason::MethodNotAllowed => "The request method was not `POST`.",
ErrorReason::Unregistered => "The device token is inactive for the specified topic. You should stop sending notifications to this token.",
ErrorReason::PayloadTooLarge => "The message payload was too large (4096 bytes)",
ErrorReason::TooManyProviderTokenUpdates => "The provider token is being updated too often.",
ErrorReason::TooManyRequests => "Too many requests were made consecutively to the same device token.",
ErrorReason::InternalServerError => "An internal server error occurred.",
ErrorReason::ServiceUnavailable => "The service is unavailable.",
ErrorReason::Shutdown => "The server is shutting down.",
ErrorReason::BadCollapseId =>
"The collapse identifier exceeds the maximum allowed size.",
ErrorReason::BadDeviceToken =>
"The specified device token was bad. Verify that the request contains a valid token and that the token matches the environment.",
ErrorReason::BadExpirationDate =>
"The `apns_expiration` in `NotificationOptions` is bad.",
ErrorReason::BadMessageId =>
"The `apns_id` in `NotificationOptions` is bad.",
ErrorReason::BadPriority =>
"The `apns_priority` in `NotificationOptions` is bad.",
ErrorReason::BadTopic =>
"The `apns_topic` in `NotificationOptions` is bad.",
ErrorReason::DeviceTokenNotForTopic =>
"The device token does not match the specified topic.",
ErrorReason::DuplicateHeaders =>
"One or more headers were repeated.",
ErrorReason::IdleTimeout =>
"Idle time out.",
ErrorReason::MissingDeviceToken =>
"The device token is not specified in the payload.",
ErrorReason::MissingTopic =>
"The `apns_topic` of the `NotificationOptions` was not specified and was required. The `apns_topic` header is mandatory when the client is connected using the `CertificateConnector` and the included PKCS12 file includes multiple topics, or when using the `TokenConnector`.",
ErrorReason::PayloadEmpty =>
"The message payload was empty.",
ErrorReason::TopicDisallowed =>
"Pushing to this topic is not allowed.",
ErrorReason::BadCertificate =>
"The certificate was bad.",
ErrorReason::BadCertificateEnvironment =>
"The client certificate was for the wrong environment.",
ErrorReason::ExpiredProviderToken =>
"The provider token is stale and a new token should be generated.",
ErrorReason::Forbidden =>
"The specified action is not allowed.",
ErrorReason::InvalidProviderToken =>
"The provider token is not valid or the token signature could not be verified.",
ErrorReason::MissingProviderToken =>
"No provider certificate was used to connect to APNs and Authorization header was missing or no provider token was specified.",
ErrorReason::BadPath =>
"The request path value is bad.",
ErrorReason::MethodNotAllowed =>
"The request method was not `POST`.",
ErrorReason::Unregistered =>
"The device token is inactive for the specified topic. You should stop sending notifications to this token.",
ErrorReason::PayloadTooLarge =>
"The message payload was too large (4096 bytes)",
ErrorReason::TooManyProviderTokenUpdates =>
"The provider token is being updated too often.",
ErrorReason::TooManyRequests =>
"Too many requests were made consecutively to the same device token.",
ErrorReason::InternalServerError =>
"An internal server error occurred.",
ErrorReason::ServiceUnavailable =>
"The service is unavailable.",
ErrorReason::Shutdown =>
"The server is shutting down.",
};
f.write_str(s)
+1 -1
View File
@@ -7,7 +7,7 @@ use openssl::pkey::{PKey, Private};
use openssl::hash::MessageDigest;
use openssl::sign::Signer as SslSigner;
use base64::encode;
use error::Error;
use crate::error::Error;
use crossbeam::atomic::ArcCell;
#[derive(Debug)]