From bfa96cd49f6546917eaf34cfbfc12a1cc58fb148 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Fri, 1 May 2020 17:15:07 +0200 Subject: [PATCH 1/9] Initial commit --- .gitignore | 2 ++ Cargo.toml | 16 +++++++++++++ LICENSE | 19 +++++++++++++++ README.md | 7 ++++++ src/lib.rs | 5 ++++ src/push.rs | 37 ++++++++++++++++++++++++++++++ src/push/tweak_serde.rs | 51 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 137 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/lib.rs create mode 100644 src/push.rs create mode 100644 src/push/tweak_serde.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..96ef6c0b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..13866cae --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ruma-common" +version = "0.1.0" +authors = ["Jonas Platte "] +description = "Common types for other ruma crates." +homepage = "https://github.com/ruma/ruma-common" +keywords = ["matrix", "chat", "messaging", "ruma"] +license = "MIT" +readme = "README.md" +repository = "https://github.com/ruma/ruma-client-api" +edition = "2018" + +[dependencies] +ruma-serde = "0.1.2" +serde = { version = "1.0.106", features = ["derive"] } +serde_json = { version = "1.0.52", features = ["raw_value"] } diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f0d48ccb --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 Jonas Platte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..ad707407 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# ruma-common + +Common types for other ruma crates. + +This crate is meant to be a dependency for other ruma crates only, consumers of +those crates should never have to use this directly (its types will be +re-exported from the other crates). diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..6849d043 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +//! Common types for other ruma crates. + +#![warn(missing_docs)] + +pub mod push; diff --git a/src/push.rs b/src/push.rs new file mode 100644 index 00000000..94877976 --- /dev/null +++ b/src/push.rs @@ -0,0 +1,37 @@ +//! Common types for the [push notifications module][push] +//! +//! [push]: https://matrix.org/docs/spec/client_server/r0.6.0#id89 + +use serde::{Deserialize, Serialize}; +use serde_json::value::RawValue as RawJsonValue; + +mod tweak_serde; + +/// The `set_tweak` action. +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(from = "tweak_serde::Tweak", into = "tweak_serde::Tweak")] +pub enum Tweak { + /// A string representing the sound to be played when this notification arrives. + /// + /// A value of "default" means to play a default sound. A device may choose to alert the user by + /// some other means if appropriate, eg. vibration. + Sound(String), + + /// A boolean representing whether or not this message should be highlighted in the UI. + /// + /// This will normally take the form of presenting the message in a different color and/or + /// style. The UI might also be adjusted to draw particular attention to the room in which the + /// event occurred. If a `highlight` tweak is given with no value, its value is defined to be + /// `true`. If no highlight tweak is given at all then the value of `highlight` is defined to be + /// `false`. + Highlight(#[serde(default = "ruma_serde::default_true")] bool), + + /// A custom tweak + Custom { + /// The name of the custom tweak (`set_tweak` field) + name: String, + + /// The value of the custom tweak + value: Box, + }, +} diff --git a/src/push/tweak_serde.rs b/src/push/tweak_serde.rs new file mode 100644 index 00000000..ce7268c0 --- /dev/null +++ b/src/push/tweak_serde.rs @@ -0,0 +1,51 @@ +use serde::{Deserialize, Serialize}; +use serde_json::value::RawValue as RawJsonValue; + +/// Values for the `set_tweak` action. +#[derive(Clone, Deserialize, Serialize)] +#[serde(untagged)] +pub enum Tweak { + Sound(SoundTweak), + Highlight(HighlightTweak), + Custom { + #[serde(rename = "set_tweak")] + name: String, + value: Box, + }, +} + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[serde(tag = "set_tweak", rename = "sound")] +pub struct SoundTweak { + value: String, +} + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[serde(tag = "set_tweak", rename = "highlight")] +pub struct HighlightTweak { + value: bool, +} + +impl From for Tweak { + fn from(tweak: super::Tweak) -> Self { + use super::Tweak::*; + + match tweak { + Sound(value) => Self::Sound(SoundTweak { value }), + Highlight(value) => Self::Highlight(HighlightTweak { value }), + Custom { name, value } => Self::Custom { name, value }, + } + } +} + +impl From for super::Tweak { + fn from(tweak: Tweak) -> Self { + use Tweak::*; + + match tweak { + Sound(SoundTweak { value }) => Self::Sound(value), + Highlight(HighlightTweak { value }) => Self::Highlight(value), + Custom { name, value } => Self::Custom { name, value }, + } + } +} From 657721b1e6b9e3f08036a20b5eabc35fe05194f8 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Fri, 1 May 2020 20:32:12 +0200 Subject: [PATCH 2/9] Add push::Action --- src/push.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/src/push.rs b/src/push.rs index 94877976..f98642c2 100644 --- a/src/push.rs +++ b/src/push.rs @@ -2,11 +2,34 @@ //! //! [push]: https://matrix.org/docs/spec/client_server/r0.6.0#id89 -use serde::{Deserialize, Serialize}; +use std::fmt::{self, Formatter}; + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_json::value::RawValue as RawJsonValue; mod tweak_serde; +/// This represents the different actions that should be taken when a rule is matched, and +/// controls how notifications are delivered to the client. +/// +/// See https://matrix.org/docs/spec/client_server/r0.6.0#actions for details. +#[derive(Clone, Debug)] +#[non_exhaustive] +pub enum Action { + /// Causes matching events to generate a notification. + Notify, + + /// Prevents matching events from generating a notification. + DontNotify, + + /// Behaves like notify but homeservers may choose to coalesce multiple events + /// into a single notification. + Coalesce, + + /// Sets an entry in the 'tweaks' dictionary sent to the push gateway. + SetTweak(Tweak), +} + /// The `set_tweak` action. #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(from = "tweak_serde::Tweak", into = "tweak_serde::Tweak")] @@ -35,3 +58,62 @@ pub enum Tweak { value: Box, }, } + +impl<'de> Deserialize<'de> for Action { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use serde::de::{MapAccess, Visitor}; + + struct ActionVisitor; + impl<'de> Visitor<'de> for ActionVisitor { + type Value = Action; + + fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { + write!(formatter, "a valid action object") + } + + /// Match a simple action type + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + match v { + "notify" => Ok(Action::Notify), + "dont_notify" => Ok(Action::DontNotify), + "coalesce" => Ok(Action::Coalesce), + s => Err(E::unknown_variant( + &s, + &["notify", "dont_notify", "coalesce"], + )), + } + } + + /// Match the more complex set_tweaks action object as a key-value map + fn visit_map(self, map: A) -> Result + where + A: MapAccess<'de>, + { + Tweak::deserialize(serde::de::value::MapAccessDeserializer::new(map)) + .map(Action::SetTweak) + } + } + + deserializer.deserialize_any(ActionVisitor) + } +} + +impl Serialize for Action { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Action::Notify => serializer.serialize_unit_variant("Action", 0, "notify"), + Action::DontNotify => serializer.serialize_unit_variant("Action", 1, "dont_notify"), + Action::Coalesce => serializer.serialize_unit_variant("Action", 2, "coalesce"), + Action::SetTweak(kind) => kind.serialize(serializer), + } + } +} From cf2747cc70a69531bc083a238790ab2f4c08d03a Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Fri, 1 May 2020 23:40:26 +0200 Subject: [PATCH 3/9] Fix HighlightTweak deserialization --- Cargo.toml | 4 ++-- src/push/tweak_serde.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 13866cae..d33d8eba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruma-common" -version = "0.1.0" +version = "0.1.1" authors = ["Jonas Platte "] description = "Common types for other ruma crates." homepage = "https://github.com/ruma/ruma-common" @@ -11,6 +11,6 @@ repository = "https://github.com/ruma/ruma-client-api" edition = "2018" [dependencies] -ruma-serde = "0.1.2" +ruma-serde = "0.1.3" serde = { version = "1.0.106", features = ["derive"] } serde_json = { version = "1.0.52", features = ["raw_value"] } diff --git a/src/push/tweak_serde.rs b/src/push/tweak_serde.rs index ce7268c0..1d022ef8 100644 --- a/src/push/tweak_serde.rs +++ b/src/push/tweak_serde.rs @@ -23,6 +23,10 @@ pub struct SoundTweak { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[serde(tag = "set_tweak", rename = "highlight")] pub struct HighlightTweak { + #[serde( + default = "ruma_serde::default_true", + skip_serializing_if = "ruma_serde::is_true" + )] value: bool, } From 97255eff600f5f551af05191d4ea55614ad1b526 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Mon, 4 May 2020 22:59:32 +0200 Subject: [PATCH 4/9] Import push::Action tests from ruma-events --- Cargo.toml | 1 + src/push.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index d33d8eba..432eca9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/ruma/ruma-client-api" edition = "2018" [dependencies] +matches = "0.1.8" ruma-serde = "0.1.3" serde = { version = "1.0.106", features = ["derive"] } serde_json = { version = "1.0.52", features = ["raw_value"] } diff --git a/src/push.rs b/src/push.rs index f98642c2..0de7f2de 100644 --- a/src/push.rs +++ b/src/push.rs @@ -117,3 +117,77 @@ impl Serialize for Action { } } } + +#[cfg(test)] +mod tests { + use matches::assert_matches; + use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; + + use super::{Action, Tweak}; + + #[test] + fn serialize_string_action() { + assert_eq!(to_json_value(&Action::Notify).unwrap(), json!("notify")); + } + + #[test] + fn serialize_tweak_sound_action() { + assert_eq!( + to_json_value(&Action::SetTweak(Tweak::Sound("default".into()))).unwrap(), + json!({ "set_tweak": "sound", "value": "default" }) + ); + } + + #[test] + fn serialize_tweak_highlight_action() { + assert_eq!( + to_json_value(&Action::SetTweak(Tweak::Highlight(true))).unwrap(), + json!({ "set_tweak": "highlight" }) + ); + + assert_eq!( + to_json_value(&Action::SetTweak(Tweak::Highlight(false))).unwrap(), + json!({ "set_tweak": "highlight", "value": false }) + ); + } + + #[test] + fn deserialize_string_action() { + assert_matches!( + from_json_value::(json!("notify")).unwrap(), + Action::Notify + ); + } + + #[test] + fn deserialize_tweak_sound_action() { + let json_data = json!({ + "set_tweak": "sound", + "value": "default" + }); + assert_matches!( + &from_json_value::(json_data).unwrap(), + Action::SetTweak(Tweak::Sound(value)) if value == "default" + ); + } + + #[test] + fn deserialize_tweak_highlight_action() { + let json_data = json!({ + "set_tweak": "highlight", + "value": true + }); + assert_matches!( + from_json_value::(json_data).unwrap(), + Action::SetTweak(Tweak::Highlight(true)) + ); + } + + #[test] + fn deserialize_tweak_highlight_action_with_default_value() { + assert_matches!( + from_json_value::(json!({ "set_tweak": "highlight" })).unwrap(), + Action::SetTweak(Tweak::Highlight(true)) + ); + } +} From 88ca0cf4f8a7c3f454d100d5c3b5518a4fc88cf5 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Tue, 19 May 2020 12:33:36 +0200 Subject: [PATCH 5/9] Bump dependencies, version --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 432eca9a..d12d3208 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruma-common" -version = "0.1.1" +version = "0.1.2" authors = ["Jonas Platte "] description = "Common types for other ruma crates." homepage = "https://github.com/ruma/ruma-common" @@ -12,6 +12,6 @@ edition = "2018" [dependencies] matches = "0.1.8" -ruma-serde = "0.1.3" -serde = { version = "1.0.106", features = ["derive"] } -serde_json = { version = "1.0.52", features = ["raw_value"] } +ruma-serde = "0.2.1" +serde = { version = "1.0.110", features = ["derive"] } +serde_json = { version = "1.0.53", features = ["raw_value"] } From 1696c4743031ca61620b9b1e0094226d1367784c Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sun, 31 May 2020 20:43:28 +0200 Subject: [PATCH 6/9] Add CI --- .builds/beta.yml | 27 +++++++++++++++++++++++++++ .builds/msrv.yml | 16 ++++++++++++++++ .builds/nightly.yml | 32 ++++++++++++++++++++++++++++++++ .builds/stable.yml | 29 +++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 .builds/beta.yml create mode 100644 .builds/msrv.yml create mode 100644 .builds/nightly.yml create mode 100644 .builds/stable.yml diff --git a/.builds/beta.yml b/.builds/beta.yml new file mode 100644 index 00000000..6ee1445f --- /dev/null +++ b/.builds/beta.yml @@ -0,0 +1,27 @@ +image: archlinux +packages: + - rustup +sources: + - https://github.com/ruma/ruma-common +tasks: + - rustup: | + # We specify --profile minimal because we'd otherwise download docs + rustup toolchain install beta --profile minimal -c rustfmt -c clippy + rustup default beta + - test: | + cd ruma-common + + # We don't want the build to stop on individual failure of independent + # tools, so capture tool exit codes and set the task exit code manually + set +e + + cargo fmt -- --check + fmt_exit=$? + + cargo clippy --all-targets --all-features -- -D warnings + clippy_exit=$? + + cargo test --verbose + test_exit=$? + + exit $(( $fmt_exit || $clippy_exit || $test_exit )) diff --git a/.builds/msrv.yml b/.builds/msrv.yml new file mode 100644 index 00000000..877ee72c --- /dev/null +++ b/.builds/msrv.yml @@ -0,0 +1,16 @@ +image: archlinux +packages: + - rustup +sources: + - https://github.com/ruma/ruma-common +tasks: + - rustup: | + # We specify --profile minimal because we'd otherwise download docs + rustup toolchain install 1.40.0 --profile minimal + rustup default 1.40.0 + - test: | + cd ruma-common + + # Only make sure the code builds with the MSRV. Tests can require later + # Rust versions, don't compile or run them. + cargo build --verbose diff --git a/.builds/nightly.yml b/.builds/nightly.yml new file mode 100644 index 00000000..42b167f6 --- /dev/null +++ b/.builds/nightly.yml @@ -0,0 +1,32 @@ +image: archlinux +packages: + - rustup +sources: + - https://github.com/ruma/ruma-common +tasks: + - rustup: | + rustup toolchain install nightly --profile minimal + rustup default nightly + + # Try installing rustfmt & clippy for nightly, but don't fail the build + # if they are not available + rustup component add rustfmt || true + rustup component add clippy || true + - test: | + cd ruma-common + + # We don't want the build to stop on individual failure of independent + # tools, so capture tool exit codes and set the task exit code manually + set +e + + if ( rustup component list | grep -q rustfmt ); then + cargo fmt -- --check + fi + fmt_exit=$? + + if ( rustup component list | grep -q clippy ); then + cargo clippy --all-targets --all-features -- -D warnings + fi + clippy_exit=$? + + exit $(( $fmt_exit || $clippy_exit )) diff --git a/.builds/stable.yml b/.builds/stable.yml new file mode 100644 index 00000000..60d31426 --- /dev/null +++ b/.builds/stable.yml @@ -0,0 +1,29 @@ +image: archlinux +packages: + - rustup +sources: + - https://github.com/ruma/ruma-common +tasks: + - rustup: | + # We specify --profile minimal because we'd otherwise download docs + rustup toolchain install stable --profile minimal -c rustfmt -c clippy + rustup default stable + - test: | + cd ruma-common + + # We don't want the build to stop on individual failure of independent + # tools, so capture tool exit codes and set the task exit code manually + set +e + + cargo fmt -- --check + fmt_exit=$? + + cargo clippy --all-targets --all-features -- -D warnings + clippy_exit=$? + + cargo test --verbose + test_exit=$? + + exit $(( $fmt_exit || $clippy_exit || $test_exit )) + # TODO: Add audit task once cargo-audit binary releases are available. + # See https://github.com/RustSec/cargo-audit/issues/66 From a79c3d51e09f252e86fbb7b592a43f7d3e9ac3ef Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Thu, 4 Jun 2020 21:07:27 +0200 Subject: [PATCH 7/9] Add presence module --- Cargo.toml | 5 +++-- src/lib.rs | 1 + src/presence.rs | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/presence.rs diff --git a/Cargo.toml b/Cargo.toml index d12d3208..5fbb0160 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ edition = "2018" [dependencies] matches = "0.1.8" -ruma-serde = "0.2.1" -serde = { version = "1.0.110", features = ["derive"] } +ruma-serde = "0.2.2" +serde = { version = "1.0.111", features = ["derive"] } serde_json = { version = "1.0.53", features = ["raw_value"] } +strum = { version = "0.18.0", features = ["derive"] } diff --git a/src/lib.rs b/src/lib.rs index 6849d043..7f8a83a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,5 @@ #![warn(missing_docs)] +pub mod presence; pub mod push; diff --git a/src/presence.rs b/src/presence.rs new file mode 100644 index 00000000..2931095e --- /dev/null +++ b/src/presence.rs @@ -0,0 +1,23 @@ +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumString}; + +/// A description of a user's connectivity and availability for chat. +#[derive(Clone, Copy, Debug, PartialEq, Display, EnumString, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "snake_case")] +pub enum PresenceState { + /// Disconnected from the service. + Offline, + + /// Connected to the service. + Online, + + /// Connected to the service but not available for chat. + Unavailable, +} + +impl Default for PresenceState { + fn default() -> Self { + Self::Online + } +} From 99876ca330a735a05626505c93ef0d5874bf903f Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Thu, 4 Jun 2020 21:08:48 +0200 Subject: [PATCH 8/9] Bump version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5fbb0160..19f2a0ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruma-common" -version = "0.1.2" +version = "0.1.3" authors = ["Jonas Platte "] description = "Common types for other ruma crates." homepage = "https://github.com/ruma/ruma-common" From b516c0cd72c1a5e9985905f60b956c5365cd8789 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Fri, 5 Jun 2020 01:37:56 +0200 Subject: [PATCH 9/9] Add presence module documentation --- src/presence.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/presence.rs b/src/presence.rs index 2931095e..52c33556 100644 --- a/src/presence.rs +++ b/src/presence.rs @@ -1,3 +1,7 @@ +//! Common types for the [presence module][presence] +//! +//! [presence]: https://matrix.org/docs/spec/client_server/r0.6.1#id62 + use serde::{Deserialize, Serialize}; use strum::{Display, EnumString};