Replace serde module with ruma-serde, update deps
This commit is contained in:
parent
23dbea1f56
commit
6ff7d3710b
11
Cargo.toml
11
Cargo.toml
@ -15,10 +15,11 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
http = "0.2.1"
|
http = "0.2.1"
|
||||||
js_int = { version = "0.1.4", features = ["serde"] }
|
js_int = { version = "0.1.4", features = ["serde"] }
|
||||||
ruma-api = "0.15.0"
|
ruma-api = "0.16.0-rc.1"
|
||||||
ruma-events = "0.18.0"
|
ruma-events = "0.19.0-rc.1"
|
||||||
ruma-identifiers = "0.14.1"
|
ruma-identifiers = "0.15.1"
|
||||||
serde = { version = "1.0.105", features = ["derive"] }
|
ruma-serde = "0.1.0"
|
||||||
serde_json = "1.0.50"
|
serde = { version = "1.0.106", features = ["derive"] }
|
||||||
|
serde_json = "1.0.51"
|
||||||
strum = { version = "0.18.0", features = ["derive"] }
|
strum = { version = "0.18.0", features = ["derive"] }
|
||||||
url = { version = "2.1.1", features = ["serde"] }
|
url = { version = "2.1.1", features = ["serde"] }
|
||||||
|
@ -12,6 +12,4 @@ pub mod error;
|
|||||||
pub mod r0;
|
pub mod r0;
|
||||||
pub mod unversioned;
|
pub mod unversioned;
|
||||||
|
|
||||||
mod serde;
|
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
@ -55,7 +55,7 @@ ruma_api! {
|
|||||||
pub kind: Option<RegistrationKind>,
|
pub kind: Option<RegistrationKind>,
|
||||||
/// If `true`, an `access_token` and `device_id` should not be returned
|
/// If `true`, an `access_token` and `device_id` should not be returned
|
||||||
/// from this call, therefore preventing an automatic login.
|
/// from this call, therefore preventing an automatic login.
|
||||||
#[serde(default, skip_serializing_if = "crate::serde::is_default")]
|
#[serde(default, skip_serializing_if = "ruma_serde::is_default")]
|
||||||
pub inhibit_login: bool,
|
pub inhibit_login: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ ruma_api! {
|
|||||||
/// Homeserver domain for verification of user's identity.
|
/// Homeserver domain for verification of user's identity.
|
||||||
pub matrix_server_name: String,
|
pub matrix_server_name: String,
|
||||||
/// Seconds until token expiration.
|
/// Seconds until token expiration.
|
||||||
#[serde(with = "crate::serde::duration::secs")]
|
#[serde(with = "ruma_serde::duration::secs")]
|
||||||
pub expires_in: Duration,
|
pub expires_in: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +38,10 @@ pub struct ThirdPartyIdentifier {
|
|||||||
/// The medium of third party identifier.
|
/// The medium of third party identifier.
|
||||||
pub medium: Medium,
|
pub medium: Medium,
|
||||||
/// The time when the identifier was validated by the identity server.
|
/// The time when the identifier was validated by the identity server.
|
||||||
#[serde(with = "crate::serde::time::ms_since_unix_epoch")]
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
pub validated_at: SystemTime,
|
pub validated_at: SystemTime,
|
||||||
/// The time when the homeserver associated the third party identifier with the user.
|
/// The time when the homeserver associated the third party identifier with the user.
|
||||||
#[serde(with = "crate::serde::time::ms_since_unix_epoch")]
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
pub added_at: SystemTime,
|
pub added_at: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ pub struct Device {
|
|||||||
pub ip: Option<String>,
|
pub ip: Option<String>,
|
||||||
/// Unix timestamp that the session was last active.
|
/// Unix timestamp that the session was last active.
|
||||||
#[serde(
|
#[serde(
|
||||||
with = "crate::serde::time::opt_ms_since_unix_epoch",
|
with = "ruma_serde::time::opt_ms_since_unix_epoch",
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none"
|
skip_serializing_if = "Option::is_none"
|
||||||
)]
|
)]
|
||||||
|
@ -40,7 +40,7 @@ ruma_api! {
|
|||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub filter: Option<Filter>,
|
pub filter: Option<Filter>,
|
||||||
/// Network to fetch the public room lists from.
|
/// Network to fetch the public room lists from.
|
||||||
#[serde(flatten, skip_serializing_if = "crate::serde::is_default")]
|
#[serde(flatten, skip_serializing_if = "ruma_serde::is_default")]
|
||||||
pub room_network: RoomNetwork,
|
pub room_network: RoomNetwork,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ ruma_api! {
|
|||||||
/// The time (in milliseconds) to wait when downloading keys from remote servers.
|
/// The time (in milliseconds) to wait when downloading keys from remote servers.
|
||||||
/// 10 seconds is the recommended default.
|
/// 10 seconds is the recommended default.
|
||||||
#[serde(
|
#[serde(
|
||||||
with = "crate::serde::duration::opt_ms",
|
with = "ruma_serde::duration::opt_ms",
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
)]
|
)]
|
||||||
|
@ -22,7 +22,7 @@ ruma_api! {
|
|||||||
/// The time (in milliseconds) to wait when downloading keys from remote servers.
|
/// The time (in milliseconds) to wait when downloading keys from remote servers.
|
||||||
/// 10 seconds is the recommended default.
|
/// 10 seconds is the recommended default.
|
||||||
#[serde(
|
#[serde(
|
||||||
with = "crate::serde::duration::opt_ms",
|
with = "ruma_serde::duration::opt_ms",
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
)]
|
)]
|
||||||
|
@ -21,7 +21,7 @@ ruma_api! {
|
|||||||
pub url: String,
|
pub url: String,
|
||||||
/// Preferred point in time (in milliseconds) to return a preview for.
|
/// Preferred point in time (in milliseconds) to return a preview for.
|
||||||
#[ruma_api(query)]
|
#[ruma_api(query)]
|
||||||
#[serde(with = "crate::serde::time::ms_since_unix_epoch")]
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
pub ts: SystemTime,
|
pub ts: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ ruma_api! {
|
|||||||
/// A RoomEventFilter to filter returned events with.
|
/// A RoomEventFilter to filter returned events with.
|
||||||
#[ruma_api(query)]
|
#[ruma_api(query)]
|
||||||
#[serde(
|
#[serde(
|
||||||
with = "crate::serde::json_string",
|
with = "ruma_serde::json_string",
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none"
|
skip_serializing_if = "Option::is_none"
|
||||||
)]
|
)]
|
||||||
|
@ -31,7 +31,7 @@ ruma_api! {
|
|||||||
pub currently_active: Option<bool>,
|
pub currently_active: Option<bool>,
|
||||||
/// The length of time in milliseconds since an action was performed by the user.
|
/// The length of time in milliseconds since an action was performed by the user.
|
||||||
#[serde(
|
#[serde(
|
||||||
with = "crate::serde::duration::opt_ms",
|
with = "ruma_serde::duration::opt_ms",
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
)]
|
)]
|
||||||
|
@ -74,6 +74,6 @@ pub struct Notification {
|
|||||||
pub room_id: RoomId,
|
pub room_id: RoomId,
|
||||||
|
|
||||||
/// The time at which the event notification was sent, in milliseconds.
|
/// The time at which the event notification was sent, in milliseconds.
|
||||||
#[serde(with = "crate::serde::time::ms_since_unix_epoch")]
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
pub ts: SystemTime,
|
pub ts: SystemTime,
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ pub struct ConnectionInfo {
|
|||||||
/// Most recently seen IP address of the session.
|
/// Most recently seen IP address of the session.
|
||||||
pub ip: String,
|
pub ip: String,
|
||||||
/// Time when that the session was last active.
|
/// Time when that the session was last active.
|
||||||
#[serde(with = "crate::serde::time::ms_since_unix_epoch")]
|
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||||
pub last_seen: SystemTime,
|
pub last_seen: SystemTime,
|
||||||
/// User agent string last seen in the session.
|
/// User agent string last seen in the session.
|
||||||
pub user_agent: String,
|
pub user_agent: String,
|
||||||
|
@ -17,10 +17,7 @@ use ruma_events::{
|
|||||||
use ruma_identifiers::RoomId;
|
use ruma_identifiers::RoomId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::r0::{filter::FilterDefinition, keys::KeyAlgorithm};
|
||||||
r0::{filter::FilterDefinition, keys::KeyAlgorithm},
|
|
||||||
serde::is_default,
|
|
||||||
};
|
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata {
|
metadata {
|
||||||
@ -45,16 +42,16 @@ ruma_api! {
|
|||||||
#[ruma_api(query)]
|
#[ruma_api(query)]
|
||||||
pub since: Option<String>,
|
pub since: Option<String>,
|
||||||
/// Controls whether to include the full state for all rooms the user is a member of.
|
/// Controls whether to include the full state for all rooms the user is a member of.
|
||||||
#[serde(default, skip_serializing_if = "is_default")]
|
#[serde(default, skip_serializing_if = "ruma_serde::is_default")]
|
||||||
#[ruma_api(query)]
|
#[ruma_api(query)]
|
||||||
pub full_state: bool,
|
pub full_state: bool,
|
||||||
/// Controls whether the client is automatically marked as online by polling this API.
|
/// Controls whether the client is automatically marked as online by polling this API.
|
||||||
#[serde(default, skip_serializing_if = "is_default")]
|
#[serde(default, skip_serializing_if = "ruma_serde::is_default")]
|
||||||
#[ruma_api(query)]
|
#[ruma_api(query)]
|
||||||
pub set_presence: SetPresence,
|
pub set_presence: SetPresence,
|
||||||
/// The maximum time to poll in milliseconds before returning this request.
|
/// The maximum time to poll in milliseconds before returning this request.
|
||||||
#[serde(
|
#[serde(
|
||||||
with = "crate::serde::duration::opt_ms",
|
with = "ruma_serde::duration::opt_ms",
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
)]
|
)]
|
||||||
@ -122,7 +119,7 @@ pub enum Filter {
|
|||||||
// FilterDefinition is the first variant, JSON decoding is attempted first which is almost
|
// FilterDefinition is the first variant, JSON decoding is attempted first which is almost
|
||||||
// functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
|
// functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
|
||||||
// (there are probably some corner cases like leading whitespace)
|
// (there are probably some corner cases like leading whitespace)
|
||||||
#[serde(with = "crate::serde::json_string")]
|
#[serde(with = "ruma_serde::json_string")]
|
||||||
/// A complete filter definition serialized to JSON.
|
/// A complete filter definition serialized to JSON.
|
||||||
FilterDefinition(FilterDefinition),
|
FilterDefinition(FilterDefinition),
|
||||||
/// The ID of a filter saved on the server.
|
/// The ID of a filter saved on the server.
|
||||||
|
@ -21,7 +21,7 @@ ruma_api! {
|
|||||||
pub room_id: RoomId,
|
pub room_id: RoomId,
|
||||||
/// The length of time in milliseconds to mark this user as typing.
|
/// The length of time in milliseconds to mark this user as typing.
|
||||||
#[serde(
|
#[serde(
|
||||||
with = "crate::serde::duration::opt_ms",
|
with = "ruma_serde::duration::opt_ms",
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
)]
|
)]
|
||||||
|
@ -20,7 +20,7 @@ ruma_api! {
|
|||||||
/// The password to use.
|
/// The password to use.
|
||||||
pub password: String,
|
pub password: String,
|
||||||
/// The time-to-live in seconds.
|
/// The time-to-live in seconds.
|
||||||
#[serde(with = "crate::serde::duration::secs")]
|
#[serde(with = "ruma_serde::duration::secs")]
|
||||||
pub ttl: Duration,
|
pub ttl: Duration,
|
||||||
/// A list of TURN URIs.
|
/// A list of TURN URIs.
|
||||||
pub uris: Vec<String>,
|
pub uris: Vec<String>,
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
//! Modules to hold functions for de-/serializing remote types
|
|
||||||
|
|
||||||
pub mod duration;
|
|
||||||
pub mod json_string;
|
|
||||||
pub mod time;
|
|
||||||
|
|
||||||
pub fn is_default<T: Default + PartialEq>(val: &T) -> bool {
|
|
||||||
val == &T::default()
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
//! De-/serialization functions for `std::time::Duration` objects
|
|
||||||
|
|
||||||
pub mod opt_ms;
|
|
||||||
pub mod secs;
|
|
@ -1,102 +0,0 @@
|
|||||||
//! De-/serialization functions for `Option<std::time::Duration>` objects represented as milliseconds.
|
|
||||||
//! Delegates to `js_int::UInt` to ensure integer size is within bounds.
|
|
||||||
|
|
||||||
use std::{convert::TryFrom, time::Duration};
|
|
||||||
|
|
||||||
use js_int::UInt;
|
|
||||||
use serde::{
|
|
||||||
de::{Deserialize, Deserializer},
|
|
||||||
ser::{Error, Serialize, Serializer},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Serialize an Option<Duration>.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be
|
|
||||||
/// unambiguously represented by an f64.
|
|
||||||
pub fn serialize<S>(opt_duration: &Option<Duration>, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
match opt_duration {
|
|
||||||
Some(duration) => match UInt::try_from(duration.as_millis()) {
|
|
||||||
Ok(uint) => uint.serialize(serializer),
|
|
||||||
Err(err) => Err(S::Error::custom(err)),
|
|
||||||
},
|
|
||||||
None => serializer.serialize_none(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserializes an Option<Duration>.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be
|
|
||||||
/// unambiguously represented by an f64.
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
Ok(Option::<UInt>::deserialize(deserializer)?
|
|
||||||
.map(|millis| Duration::from_millis(millis.into())))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
|
||||||
struct DurationTest {
|
|
||||||
#[serde(with = "super", default, skip_serializing_if = "Option::is_none")]
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize_some() {
|
|
||||||
let json = json!({ "timeout": 3000 });
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<DurationTest>(json).unwrap(),
|
|
||||||
DurationTest {
|
|
||||||
timeout: Some(Duration::from_millis(3000))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize_none_by_absence() {
|
|
||||||
let json = json!({});
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<DurationTest>(json).unwrap(),
|
|
||||||
DurationTest { timeout: None },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize_none_by_null() {
|
|
||||||
let json = json!({ "timeout": null });
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<DurationTest>(json).unwrap(),
|
|
||||||
DurationTest { timeout: None },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_serialize_some() {
|
|
||||||
let request = DurationTest {
|
|
||||||
timeout: Some(Duration::new(2, 0)),
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::to_value(&request).unwrap(),
|
|
||||||
json!({ "timeout": 2000 })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_serialize_none() {
|
|
||||||
let request = DurationTest { timeout: None };
|
|
||||||
assert_eq!(serde_json::to_value(&request).unwrap(), json!({}));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
//! De-/serialization functions for `Option<std::time::Duration>` objects represented as milliseconds.
|
|
||||||
//! Delegates to `js_int::UInt` to ensure integer size is within bounds.
|
|
||||||
|
|
||||||
use std::{convert::TryFrom, time::Duration};
|
|
||||||
|
|
||||||
use js_int::UInt;
|
|
||||||
use serde::{
|
|
||||||
de::{Deserialize, Deserializer},
|
|
||||||
ser::{Error, Serialize, Serializer},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Serializes a Duration to an integer representing seconds.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be
|
|
||||||
/// unambiguously represented by an f64.
|
|
||||||
pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
match UInt::try_from(duration.as_secs()) {
|
|
||||||
Ok(uint) => uint.serialize(serializer),
|
|
||||||
Err(err) => Err(S::Error::custom(err)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserializes an integer representing seconds into a Duration.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be
|
|
||||||
/// unambiguously represented by an f64.
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
UInt::deserialize(deserializer).map(|secs| Duration::from_secs(secs.into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
|
||||||
struct DurationTest {
|
|
||||||
#[serde(with = "super")]
|
|
||||||
timeout: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize() {
|
|
||||||
let json = json!({ "timeout": 3 });
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<DurationTest>(json).unwrap(),
|
|
||||||
DurationTest {
|
|
||||||
timeout: Duration::from_secs(3)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_serialize() {
|
|
||||||
let test = DurationTest {
|
|
||||||
timeout: Duration::from_millis(7000),
|
|
||||||
};
|
|
||||||
assert_eq!(serde_json::to_value(test).unwrap(), json!({ "timeout": 7 }),);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
//! De-/serialization functions to and from json strings, allows the type to be used as a query string.
|
|
||||||
|
|
||||||
use serde::{
|
|
||||||
de::{Deserialize, DeserializeOwned, Deserializer, Error as _},
|
|
||||||
ser::{Error as _, Serialize, Serializer},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn serialize<T, S>(filter: T, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
T: Serialize,
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let json = serde_json::to_string(&filter).map_err(S::Error::custom)?;
|
|
||||||
serializer.serialize_str(&json)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
|
|
||||||
where
|
|
||||||
T: DeserializeOwned,
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let s = String::deserialize(deserializer)?;
|
|
||||||
serde_json::from_str(&s).map_err(D::Error::custom)
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
//! De-/serialization functions for `std::time::SystemTime` objects
|
|
||||||
|
|
||||||
pub mod ms_since_unix_epoch;
|
|
||||||
pub mod opt_ms_since_unix_epoch;
|
|
@ -1,78 +0,0 @@
|
|||||||
//! De-/serialization functions for `std::time::SystemTime` objects represented as milliseconds
|
|
||||||
//! since the UNIX epoch. Delegates to `js_int::UInt` to ensure integer size is within bounds.
|
|
||||||
|
|
||||||
use std::{
|
|
||||||
convert::TryFrom,
|
|
||||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
|
||||||
};
|
|
||||||
|
|
||||||
use js_int::UInt;
|
|
||||||
use serde::{
|
|
||||||
de::{Deserialize, Deserializer},
|
|
||||||
ser::{Error, Serialize, Serializer},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Serialize a SystemTime.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
|
|
||||||
/// by an f64.
|
|
||||||
pub fn serialize<S>(time: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
// If this unwrap fails, the system this is executed is completely broken.
|
|
||||||
let time_since_epoch = time.duration_since(UNIX_EPOCH).unwrap();
|
|
||||||
match UInt::try_from(time_since_epoch.as_millis()) {
|
|
||||||
Ok(uint) => uint.serialize(serializer),
|
|
||||||
Err(err) => Err(S::Error::custom(err)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserializes a SystemTime.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
|
|
||||||
/// by an f64.
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let millis = UInt::deserialize(deserializer)?;
|
|
||||||
Ok(UNIX_EPOCH + Duration::from_millis(millis.into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
|
||||||
struct SystemTimeTest {
|
|
||||||
#[serde(with = "super")]
|
|
||||||
timestamp: SystemTime,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize() {
|
|
||||||
let json = json!({ "timestamp": 3000 });
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<SystemTimeTest>(json).unwrap(),
|
|
||||||
SystemTimeTest {
|
|
||||||
timestamp: UNIX_EPOCH + Duration::from_millis(3000),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_serialize() {
|
|
||||||
let request = SystemTimeTest {
|
|
||||||
timestamp: UNIX_EPOCH + Duration::new(2, 0),
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::to_value(&request).unwrap(),
|
|
||||||
json!({ "timestamp": 2000 })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
//! De-/serialization functions for `Option<std::time::SystemTime>` objects represented as
|
|
||||||
//! milliseconds since the UNIX epoch. Delegates to `js_int::UInt` to ensure integer size is within
|
|
||||||
//! bounds.
|
|
||||||
|
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
||||||
|
|
||||||
use js_int::UInt;
|
|
||||||
use serde::{
|
|
||||||
de::{Deserialize, Deserializer},
|
|
||||||
ser::{Serialize, Serializer},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Serialize an `Option<SystemTime>`.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
|
|
||||||
/// by an f64.
|
|
||||||
pub fn serialize<S>(opt_time: &Option<SystemTime>, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
match opt_time {
|
|
||||||
Some(time) => super::ms_since_unix_epoch::serialize(time, serializer),
|
|
||||||
None => Option::<UInt>::serialize(&None, serializer),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserializes an `Option<SystemTime>`.
|
|
||||||
///
|
|
||||||
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
|
|
||||||
/// by an f64.
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<SystemTime>, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
Ok(Option::<UInt>::deserialize(deserializer)?
|
|
||||||
.map(|millis| UNIX_EPOCH + Duration::from_millis(millis.into())))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
|
||||||
struct SystemTimeTest {
|
|
||||||
#[serde(with = "super", default, skip_serializing_if = "Option::is_none")]
|
|
||||||
timestamp: Option<SystemTime>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize_some() {
|
|
||||||
let json = json!({ "timestamp": 3000 });
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<SystemTimeTest>(json).unwrap(),
|
|
||||||
SystemTimeTest {
|
|
||||||
timestamp: Some(UNIX_EPOCH + Duration::from_millis(3000))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize_none_by_absence() {
|
|
||||||
let json = json!({});
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<SystemTimeTest>(json).unwrap(),
|
|
||||||
SystemTimeTest { timestamp: None },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deserialize_none_by_null() {
|
|
||||||
let json = json!({ "timestamp": null });
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::from_value::<SystemTimeTest>(json).unwrap(),
|
|
||||||
SystemTimeTest { timestamp: None },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_serialize_some() {
|
|
||||||
let request = SystemTimeTest {
|
|
||||||
timestamp: Some(UNIX_EPOCH + Duration::new(2, 0)),
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
serde_json::to_value(&request).unwrap(),
|
|
||||||
json!({ "timestamp": 2000 })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_serialize_none() {
|
|
||||||
let request = SystemTimeTest { timestamp: None };
|
|
||||||
assert_eq!(serde_json::to_value(&request).unwrap(), json!({}));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user