Use Duration over UInt for timeouts and similar fields
This commit is contained in:
parent
7307c695e0
commit
122097cfef
11
CHANGELOG.md
11
CHANGELOG.md
@ -24,6 +24,17 @@ Breaking changes:
|
||||
* Remove deprecated endpoint `r0::contact::create_contact` (deprecated in r0.6.0)
|
||||
* Add lazy-loading options to `r0::filter::RoomEventFilter` (introduced in r0.5.0)
|
||||
* Change type for `limit` request parameter of `r0::context::get_context` from `u8` to `Option<js_int::UInt>`
|
||||
* Use `std::time::Duration` for appropriate fields on several endpoints:
|
||||
```
|
||||
r0::{
|
||||
account::request_openid_token,
|
||||
keys::{claim_keys, get_keys},
|
||||
presence::get_presence,
|
||||
sync::sync_events,
|
||||
typing::create_typing_event,
|
||||
voip::get_turn_server_info
|
||||
}
|
||||
```
|
||||
|
||||
# 0.6.0
|
||||
|
||||
|
@ -14,7 +14,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
http = "0.2.0"
|
||||
js_int = { version = "0.1.2", features = ["serde"] }
|
||||
js_int = { version = "0.1.3", features = ["serde"] }
|
||||
ruma-api = "0.14.0"
|
||||
ruma-events = "0.17.0"
|
||||
ruma-identifiers = "0.14.1"
|
||||
|
@ -11,3 +11,5 @@
|
||||
pub mod error;
|
||||
pub mod r0;
|
||||
pub mod unversioned;
|
||||
|
||||
mod serde;
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! [POST /_matrix/client/r0/user/{userId}/openid/request_token](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-openid-request-token)
|
||||
|
||||
use js_int::UInt;
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -29,7 +30,8 @@ ruma_api! {
|
||||
/// Homeserver domain for verification of user's identity.
|
||||
pub matrix_server_name: String,
|
||||
/// Seconds until token expiration.
|
||||
pub expires_in: UInt,
|
||||
#[serde(with = "crate::serde::duration::secs")]
|
||||
pub expires_in: Duration,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use js_int::UInt;
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{DeviceId, UserId};
|
||||
use serde_json::Value;
|
||||
@ -23,7 +24,8 @@ ruma_api! {
|
||||
/// The time (in milliseconds) to wait when downloading keys from remote servers.
|
||||
/// 10 seconds is the recommended default.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timeout: Option<UInt>,
|
||||
#[serde(default, with = "crate::serde::duration::opt_ms")]
|
||||
pub timeout: Option<Duration>,
|
||||
|
||||
/// The keys to be claimed.
|
||||
pub one_time_keys: HashMap<UserId, HashMap<DeviceId, KeyAlgorithm>>,
|
||||
|
@ -1,8 +1,7 @@
|
||||
//! [POST /_matrix/client/r0/keys/query](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-keys-query)
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, time::Duration};
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{DeviceId, UserId};
|
||||
use serde_json::Value;
|
||||
@ -23,7 +22,8 @@ ruma_api! {
|
||||
/// The time (in milliseconds) to wait when downloading keys from remote servers.
|
||||
/// 10 seconds is the recommended default.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timeout: Option<UInt>,
|
||||
#[serde(default, with = "crate::serde::duration::opt_ms")]
|
||||
pub timeout: Option<Duration>,
|
||||
|
||||
/// The keys to be downloaded. An empty list indicates all devices for the corresponding user.
|
||||
pub device_keys: HashMap<UserId, Vec<DeviceId>>,
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! [GET /_matrix/client/r0/presence/{userId}/status](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-presence-userid-status)
|
||||
|
||||
use js_int::UInt;
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::presence::PresenceState;
|
||||
use ruma_identifiers::UserId;
|
||||
@ -30,7 +31,8 @@ ruma_api! {
|
||||
pub currently_active: Option<bool>,
|
||||
/// The length of time in milliseconds since an action was performed by the user.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub last_active_ago: Option<UInt>,
|
||||
#[serde(default, with = "crate::serde::duration::opt_ms")]
|
||||
pub last_active_ago: Option<Duration>,
|
||||
/// The user's presence state.
|
||||
pub presence: PresenceState,
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.4.0.html#get-matrix-client-r0-sync)
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, time::Duration};
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::{ruma_api, Outgoing};
|
||||
@ -48,8 +48,9 @@ ruma_api! {
|
||||
pub set_presence: Option<SetPresence>,
|
||||
/// The maximum time to poll in milliseconds before returning this request.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(with = "crate::serde::duration::opt_ms")]
|
||||
#[ruma_api(query)]
|
||||
pub timeout: Option<UInt>,
|
||||
pub timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
response {
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! [PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}](https://matrix.org/docs/spec/client_server/r0.4.0.html#put-matrix-client-r0-rooms-roomid-typing-userid)
|
||||
|
||||
use js_int::UInt;
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
|
||||
@ -20,7 +21,8 @@ ruma_api! {
|
||||
pub room_id: RoomId,
|
||||
/// The length of time in milliseconds to mark this user as typing.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timeout: Option<UInt>,
|
||||
#[serde(default, with = "crate::serde::duration::opt_ms")]
|
||||
pub timeout: Option<Duration>,
|
||||
/// Whether the user is typing or not. If `false`, the `timeout` key can be omitted.
|
||||
pub typing: bool,
|
||||
/// The user who has started to type.
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! [GET /_matrix/client/r0/voip/turnServer](https://matrix.org/docs/spec/client_server/r0.4.0.html#get-matrix-client-r0-voip-turnserver)
|
||||
|
||||
use js_int::UInt;
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
@ -19,7 +20,8 @@ ruma_api! {
|
||||
/// The password to use.
|
||||
pub password: String,
|
||||
/// The time-to-live in seconds.
|
||||
pub ttl: UInt,
|
||||
#[serde(with = "crate::serde::duration::secs")]
|
||||
pub ttl: Duration,
|
||||
/// A list of TURN URIs.
|
||||
pub uris: Vec<String>,
|
||||
/// The username to use.
|
||||
|
3
src/serde.rs
Normal file
3
src/serde.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! Modules to hold functions for de-/serializing remote types
|
||||
|
||||
pub mod duration;
|
4
src/serde/duration.rs
Normal file
4
src/serde/duration.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//! De-/serialization functions for `std::time::Duration` objects
|
||||
|
||||
pub mod opt_ms;
|
||||
pub mod secs;
|
90
src/serde/duration/opt_ms.rs
Normal file
90
src/serde/duration/opt_ms.rs
Normal file
@ -0,0 +1,90 @@
|
||||
//! 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 serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
struct DurationTest {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(default, with = "crate::serde::duration::opt_ms")]
|
||||
timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_some_duration_as_milliseconds() {
|
||||
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_empty_duration_as_milliseconds() {
|
||||
let json = json!({});
|
||||
|
||||
assert_eq!(
|
||||
serde_json::from_value::<DurationTest>(json).unwrap(),
|
||||
DurationTest { timeout: None },
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_some_duration_as_milliseconds() {
|
||||
let request = DurationTest {
|
||||
timeout: Some(Duration::new(2, 0)),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(&request).unwrap(),
|
||||
json!({ "timeout": 2000 })
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_empty_duration_as_milliseconds() {
|
||||
let request = DurationTest { timeout: None };
|
||||
assert_eq!(serde_json::to_value(&request).unwrap(), json!({}));
|
||||
}
|
||||
}
|
66
src/serde/duration/secs.rs
Normal file
66
src/serde/duration/secs.rs
Normal file
@ -0,0 +1,66 @@
|
||||
//! 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 serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
struct DurationTest {
|
||||
#[serde(with = "crate::serde::duration::secs")]
|
||||
timeout: Duration,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_duration_as_seconds() {
|
||||
let json = json!({ "timeout": 3 });
|
||||
|
||||
assert_eq!(
|
||||
serde_json::from_value::<DurationTest>(json).unwrap(),
|
||||
DurationTest {
|
||||
timeout: Duration::from_secs(3)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_duration_as_seconds() {
|
||||
let test = DurationTest {
|
||||
timeout: Duration::from_millis(7000),
|
||||
};
|
||||
assert_eq!(serde_json::to_value(test).unwrap(), json!({ "timeout": 7 }),);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user