Add 'ruma-common/' from commit 'b516c0cd72c1a5e9985905f60b956c5365cd8789'
git-subtree-dir: ruma-common git-subtree-mainline:c186f0f8c9
git-subtree-split:b516c0cd72
This commit is contained in:
commit
40b51d73a3
12 changed files with 431 additions and 0 deletions
27
ruma-common/.builds/beta.yml
Normal file
27
ruma-common/.builds/beta.yml
Normal file
|
@ -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 ))
|
16
ruma-common/.builds/msrv.yml
Normal file
16
ruma-common/.builds/msrv.yml
Normal file
|
@ -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
|
32
ruma-common/.builds/nightly.yml
Normal file
32
ruma-common/.builds/nightly.yml
Normal file
|
@ -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 ))
|
29
ruma-common/.builds/stable.yml
Normal file
29
ruma-common/.builds/stable.yml
Normal file
|
@ -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
|
2
ruma-common/.gitignore
vendored
Normal file
2
ruma-common/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
Cargo.lock
|
18
ruma-common/Cargo.toml
Normal file
18
ruma-common/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "ruma-common"
|
||||
version = "0.1.3"
|
||||
authors = ["Jonas Platte <jplatte@posteo.de>"]
|
||||
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]
|
||||
matches = "0.1.8"
|
||||
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"] }
|
19
ruma-common/LICENSE
Normal file
19
ruma-common/LICENSE
Normal file
|
@ -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.
|
7
ruma-common/README.md
Normal file
7
ruma-common/README.md
Normal file
|
@ -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).
|
6
ruma-common/src/lib.rs
Normal file
6
ruma-common/src/lib.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
//! Common types for other ruma crates.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
pub mod presence;
|
||||
pub mod push;
|
27
ruma-common/src/presence.rs
Normal file
27
ruma-common/src/presence.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
//! 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};
|
||||
|
||||
/// 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
|
||||
}
|
||||
}
|
193
ruma-common/src/push.rs
Normal file
193
ruma-common/src/push.rs
Normal file
|
@ -0,0 +1,193 @@
|
|||
//! Common types for the [push notifications module][push]
|
||||
//!
|
||||
//! [push]: https://matrix.org/docs/spec/client_server/r0.6.0#id89
|
||||
|
||||
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")]
|
||||
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<RawJsonValue>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Action {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
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<A>(self, map: A) -> Result<Self::Value, A::Error>
|
||||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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::<Action>(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::<Action>(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::<Action>(json_data).unwrap(),
|
||||
Action::SetTweak(Tweak::Highlight(true))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_tweak_highlight_action_with_default_value() {
|
||||
assert_matches!(
|
||||
from_json_value::<Action>(json!({ "set_tweak": "highlight" })).unwrap(),
|
||||
Action::SetTweak(Tweak::Highlight(true))
|
||||
);
|
||||
}
|
||||
}
|
55
ruma-common/src/push/tweak_serde.rs
Normal file
55
ruma-common/src/push/tweak_serde.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
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<RawJsonValue>,
|
||||
},
|
||||
}
|
||||
|
||||
#[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 {
|
||||
#[serde(
|
||||
default = "ruma_serde::default_true",
|
||||
skip_serializing_if = "ruma_serde::is_true"
|
||||
)]
|
||||
value: bool,
|
||||
}
|
||||
|
||||
impl From<super::Tweak> 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<Tweak> 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 },
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue