use std::collections::BTreeMap;
use ruma_identifiers::{RoomAliasId, UserId};
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::MilliSecondsSinceUnixEpoch;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Protocol {
pub user_fields: Vec<String>,
pub location_fields: Vec<String>,
#[cfg_attr(feature = "compat", serde(default))]
pub icon: String,
pub field_types: BTreeMap<String, FieldType>,
pub instances: Vec<ProtocolInstance>,
}
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct ProtocolInit {
pub user_fields: Vec<String>,
pub location_fields: Vec<String>,
pub icon: String,
pub field_types: BTreeMap<String, FieldType>,
pub instances: Vec<ProtocolInstance>,
}
impl From<ProtocolInit> for Protocol {
fn from(init: ProtocolInit) -> Self {
let ProtocolInit { user_fields, location_fields, icon, field_types, instances } = init;
Self { user_fields, location_fields, icon, field_types, instances }
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ProtocolInstance {
pub desc: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub icon: Option<String>,
pub fields: BTreeMap<String, String>,
pub network_id: String,
#[cfg(feature = "unstable-pre-spec")]
pub instance_id: String,
}
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct ProtocolInstanceInit {
pub desc: String,
pub fields: BTreeMap<String, String>,
pub network_id: String,
#[cfg(feature = "unstable-pre-spec")]
pub instance_id: String,
}
impl From<ProtocolInstanceInit> for ProtocolInstance {
fn from(init: ProtocolInstanceInit) -> Self {
let ProtocolInstanceInit {
desc,
fields,
network_id,
#[cfg(feature = "unstable-pre-spec")]
instance_id,
} = init;
Self {
desc,
icon: None,
fields,
network_id,
#[cfg(feature = "unstable-pre-spec")]
instance_id,
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct FieldType {
pub regexp: String,
pub placeholder: String,
}
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct FieldTypeInit {
pub regexp: String,
pub placeholder: String,
}
impl From<FieldTypeInit> for FieldType {
fn from(init: FieldTypeInit) -> Self {
let FieldTypeInit { regexp, placeholder } = init;
Self { regexp, placeholder }
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Location {
pub alias: RoomAliasId,
pub protocol: String,
pub fields: BTreeMap<String, String>,
}
impl Location {
pub fn new(alias: RoomAliasId, protocol: String, fields: BTreeMap<String, String>) -> Self {
Self { alias, protocol, fields }
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct User {
pub userid: UserId,
pub protocol: String,
pub fields: BTreeMap<String, String>,
}
impl User {
pub fn new(userid: UserId, protocol: String, fields: BTreeMap<String, String>) -> Self {
Self { userid, protocol, fields }
}
}
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "lowercase")]
pub enum Medium {
Email,
Msisdn,
#[doc(hidden)]
_Custom(String),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[cfg_attr(test, derive(PartialEq))]
pub struct ThirdPartyIdentifier {
pub address: String,
pub medium: Medium,
pub validated_at: MilliSecondsSinceUnixEpoch,
pub added_at: MilliSecondsSinceUnixEpoch,
}
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct ThirdPartyIdentifierInit {
pub address: String,
pub medium: Medium,
pub validated_at: MilliSecondsSinceUnixEpoch,
pub added_at: MilliSecondsSinceUnixEpoch,
}
impl From<ThirdPartyIdentifierInit> for ThirdPartyIdentifier {
fn from(init: ThirdPartyIdentifierInit) -> Self {
let ThirdPartyIdentifierInit { address, medium, validated_at, added_at } = init;
ThirdPartyIdentifier { address, medium, validated_at, added_at }
}
}
#[cfg(test)]
mod tests {
use std::convert::TryInto;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::{Medium, ThirdPartyIdentifier};
use crate::MilliSecondsSinceUnixEpoch;
#[test]
fn third_party_identifier_serde() {
let third_party_id = ThirdPartyIdentifier {
address: "monkey@banana.island".into(),
medium: Medium::Email,
validated_at: MilliSecondsSinceUnixEpoch(1_535_176_800_000_u64.try_into().unwrap()),
added_at: MilliSecondsSinceUnixEpoch(1_535_336_848_756_u64.try_into().unwrap()),
};
let third_party_id_serialized = json!({
"medium": "email",
"address": "monkey@banana.island",
"validated_at": 1_535_176_800_000_u64,
"added_at": 1_535_336_848_756_u64
});
assert_eq!(to_json_value(third_party_id.clone()).unwrap(), third_party_id_serialized);
assert_eq!(third_party_id, from_json_value(third_party_id_serialized).unwrap());
}
}