Make the inner type of _Custom enum variants unusable

The variant itself would be private if possible, this is the solution
closest to that.
This commit is contained in:
Jonas Platte 2022-01-13 00:51:01 +01:00
parent f8ba7f7957
commit ee977b48f0
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
52 changed files with 235 additions and 101 deletions

View File

@ -11,6 +11,8 @@ use ruma_identifiers::RoomVersionId;
use serde::{Deserialize, Serialize};
use serde_json::{from_slice as from_json_slice, Value as JsonValue};
use crate::PrivOwnedStr;
/// Deserialize and Serialize implementations for ErrorKind.
/// Separate module because it's a lot of code.
mod kind_serde;
@ -18,7 +20,7 @@ mod kind_serde;
/// An enum for the error kind.
///
/// Items may contain additional information.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ErrorKind {
/// M_FORBIDDEN
@ -135,9 +137,13 @@ pub enum ErrorKind {
CannotLeaveServerNoticeRoom,
#[doc(hidden)]
_Custom { errcode: String, extra: BTreeMap<String, JsonValue> },
_Custom { errcode: PrivOwnedStr, extra: Extra },
}
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Extra(BTreeMap<String, JsonValue>);
impl AsRef<str> for ErrorKind {
fn as_ref(&self) -> &str {
match self {
@ -173,7 +179,7 @@ impl AsRef<str> for ErrorKind {
Self::Exclusive => "M_EXCLUSIVE",
Self::ResourceLimitExceeded { .. } => "M_RESOURCE_LIMIT_EXCEEDED",
Self::CannotLeaveServerNoticeRoom => "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM",
Self::_Custom { errcode, .. } => errcode,
Self::_Custom { errcode, .. } => &errcode.0,
}
}
}

View File

@ -14,7 +14,8 @@ use serde::{
};
use serde_json::from_value as from_json_value;
use super::ErrorKind;
use super::{ErrorKind, Extra};
use crate::PrivOwnedStr;
enum Field<'de> {
ErrCode,
@ -147,6 +148,8 @@ impl<'de> Visitor<'de> for ErrorKindVisitor {
}
let errcode = errcode.ok_or_else(|| de::Error::missing_field("errcode"))?;
let extra = Extra(extra);
Ok(match errcode {
ErrCode::Forbidden => ErrorKind::Forbidden,
ErrCode::UnknownToken => ErrorKind::UnknownToken {
@ -243,7 +246,7 @@ enum ErrCode {
Exclusive,
ResourceLimitExceeded,
CannotLeaveServerNoticeRoom,
_Custom(String),
_Custom(PrivOwnedStr),
}
impl<'de> Deserialize<'de> for ErrorKind {
@ -279,7 +282,7 @@ impl Serialize for ErrorKind {
st.serialize_entry("admin_contact", admin_contact)?;
}
Self::_Custom { extra, .. } => {
for (k, v) in extra {
for (k, v) in &extra.0 {
st.serialize_entry(k, v)?;
}
}

View File

@ -13,3 +13,10 @@ pub mod r0;
pub mod unversioned;
pub use error::Error;
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
// this crate. Used for string enums because their `_Custom` variant can't be
// truly private (only `#[doc(hidden)]`).
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -23,6 +23,8 @@ pub mod whoami;
use ruma_serde::{Outgoing, StringEnum};
use serde::Serialize;
use crate::PrivOwnedStr;
/// Additional authentication information for requestToken endpoints.
#[derive(Clone, Debug, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
@ -58,7 +60,7 @@ pub enum ThirdPartyIdRemovalStatus {
Success,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl ThirdPartyIdRemovalStatus {

View File

@ -10,6 +10,8 @@ use serde_json::{from_value as from_json_value, to_value as to_json_value, Value
use iter::{CapabilitiesIter, CapabilityRef};
use crate::PrivOwnedStr;
pub mod get_capabilities;
pub mod iter;
@ -176,7 +178,7 @@ pub enum RoomVersionStability {
Unstable,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl RoomVersionStability {

View File

@ -14,6 +14,8 @@ use ruma_identifiers::{RoomId, UserId};
use ruma_serde::{Outgoing, StringEnum};
use serde::Serialize;
use crate::PrivOwnedStr;
/// Format to use for returned events.
///
/// This type can hold an arbitrary string. To check for formats that are not available as a
@ -29,7 +31,7 @@ pub enum EventFormat {
Federation,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl EventFormat {

View File

@ -5,6 +5,8 @@ use ruma_api::ruma_api;
use ruma_identifiers::{Error, MxcUri, ServerName};
use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
ruma_api! {
metadata: {
description: "Get a thumbnail of content from the media store.",
@ -100,7 +102,7 @@ pub enum Method {
Scale,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Method {

View File

@ -5,6 +5,8 @@ use ruma_events::room::member::RoomMemberEvent;
use ruma_identifiers::RoomId;
use ruma_serde::{Raw, StringEnum};
use crate::PrivOwnedStr;
ruma_api! {
metadata: {
description: "Get membership events for a room.",
@ -88,7 +90,7 @@ pub enum MembershipEventFilter {
Ban,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl MembershipEventFilter {

View File

@ -8,6 +8,8 @@ use ruma_common::push::{
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
pub mod delete_pushrule;
pub mod get_notifications;
pub mod get_pushers;
@ -184,7 +186,7 @@ pub enum RuleKind {
Content,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl RuleKind {
@ -209,7 +211,7 @@ pub enum PusherKind {
Email,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl PusherKind {

View File

@ -8,6 +8,8 @@ pub mod upgrade_room;
use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
/// Whether or not a newly created room will be listed in the room directory.
///
/// This type can hold an arbitrary string. To check for formats that are not available as a
@ -23,7 +25,7 @@ pub enum Visibility {
Private,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Visibility {

View File

@ -16,7 +16,10 @@ use ruma_serde::{Raw, StringEnum};
use serde::{Deserialize, Serialize};
use super::Visibility;
use crate::r0::membership::{IncomingInvite3pid, Invite3pid};
use crate::{
r0::membership::{IncomingInvite3pid, Invite3pid},
PrivOwnedStr,
};
ruma_api! {
metadata: {
@ -213,7 +216,7 @@ pub enum RoomPreset {
TrustedPrivateChat,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl RoomPreset {

View File

@ -9,7 +9,10 @@ use ruma_identifiers::{EventId, MxcUri, RoomId, UserId};
use ruma_serde::{Outgoing, Raw, StringEnum};
use serde::{Deserialize, Serialize};
use crate::r0::filter::{IncomingRoomEventFilter, RoomEventFilter};
use crate::{
r0::filter::{IncomingRoomEventFilter, RoomEventFilter},
PrivOwnedStr,
};
ruma_api! {
metadata: {
@ -252,7 +255,7 @@ pub enum GroupingKey {
Sender,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl GroupingKey {
@ -304,7 +307,7 @@ pub enum SearchKeys {
ContentTopic,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl SearchKeys {
@ -327,7 +330,7 @@ pub enum OrderBy {
Rank,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
/// Categories of events that can be searched for.

View File

@ -11,6 +11,9 @@ use ruma_serde::StringEnum;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value as JsonValue;
#[cfg(feature = "unstable-pre-spec")]
use crate::PrivOwnedStr;
ruma_api! {
metadata: {
description: "Gets the homeserver's supported login types to authenticate users. Clients should pick one of these and supply it as the type when logging in.",
@ -230,7 +233,7 @@ pub enum IdentityProviderBrand {
/// A custom brand.
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
/// A custom login payload.

View File

@ -20,7 +20,10 @@ use serde_json::{
from_slice as from_json_slice, value::RawValue as RawJsonValue, Value as JsonValue,
};
use crate::error::{Error as MatrixError, ErrorBody};
use crate::{
error::{Error as MatrixError, ErrorBody},
PrivOwnedStr,
};
pub mod get_uiaa_fallback_page;
mod user_serde;
@ -85,7 +88,7 @@ impl<'a> AuthData<'a> {
#[cfg(feature = "unstable-pre-spec")]
Self::RegistrationToken(_) => Some(AuthType::RegistrationToken),
Self::FallbackAcknowledgement(_) => None,
Self::_Custom(c) => Some(AuthType::_Custom(c.auth_type.to_owned())),
Self::_Custom(c) => Some(AuthType::_Custom(PrivOwnedStr(c.auth_type.into()))),
}
}
@ -212,7 +215,7 @@ impl IncomingAuthData {
#[cfg(feature = "unstable-pre-spec")]
Self::RegistrationToken(_) => Some(AuthType::RegistrationToken),
Self::FallbackAcknowledgement(_) => None,
Self::_Custom(c) => Some(AuthType::_Custom(c.auth_type.clone())),
Self::_Custom(c) => Some(AuthType::_Custom(PrivOwnedStr(c.auth_type.as_str().into()))),
}
}
@ -384,7 +387,7 @@ pub enum AuthType {
RegistrationToken,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
/// Data for password-based UIAA flow.

View File

@ -2,6 +2,8 @@
use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
/// Access token types.
///
/// This type can hold an arbitrary string. To check for formats that are not available as a
@ -13,7 +15,7 @@ pub enum TokenType {
Bearer,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl TokenType {

View File

@ -17,3 +17,10 @@ mod time;
pub mod to_device;
pub use time::{MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch};
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
// this crate. Used for string enums because their `_Custom` variant can't be
// truly private (only `#[doc(hidden)]`).
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -4,6 +4,8 @@
use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
/// A description of a user's connectivity and availability for chat.
///
/// This type can hold an arbitrary string. To check for formats that are not available as a
@ -22,7 +24,7 @@ pub enum PresenceState {
Unavailable,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Default for PresenceState {

View File

@ -16,6 +16,8 @@
use std::hash::{Hash, Hasher};
use crate::PrivOwnedStr;
use indexmap::{Equivalent, IndexSet};
use ruma_serde::{Raw, StringEnum};
use serde::{Deserialize, Serialize};
@ -450,7 +452,7 @@ pub enum PushFormat {
EventIdOnly,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl PushFormat {

View File

@ -2,6 +2,8 @@
use ruma_serde::{OrdAsRefStr, PartialEqAsRefStr, PartialOrdAsRefStr, StringEnum};
use crate::PrivOwnedStr;
/// The type of receipt.
///
/// This type can hold an arbitrary string. To check for formats that are not available as a
@ -14,7 +16,7 @@ pub enum ReceiptType {
Read,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl ReceiptType {

View File

@ -8,7 +8,7 @@ use ruma_identifiers::{RoomAliasId, UserId};
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::MilliSecondsSinceUnixEpoch;
use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr};
/// Metadata about a third party protocol.
///
@ -229,7 +229,7 @@ pub enum Medium {
Msisdn,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Medium {

View File

@ -136,7 +136,7 @@ fn generate_enum(
#variants,
)*
#[doc(hidden)]
_Custom(String),
_Custom(crate::PrivOwnedStr),
}
impl #ident {

View File

@ -5,6 +5,8 @@
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
pub mod answer;
pub mod candidates;
pub mod hangup;
@ -44,7 +46,7 @@ pub enum SessionDescriptionType {
Offer,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl SessionDescriptionType {

View File

@ -7,6 +7,8 @@ use ruma_events_macros::EventContent;
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.call.hangup` event.
///
/// Sent by either party to signal their termination of the call. This can be sent either once the
@ -52,7 +54,7 @@ pub enum Reason {
InviteTimeout,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Reason {

View File

@ -12,6 +12,8 @@ use ruma_serde::StringEnum;
#[cfg(feature = "unstable-pre-spec")]
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
pub mod accept;
pub mod cancel;
#[cfg(feature = "unstable-pre-spec")]
@ -35,7 +37,7 @@ pub enum HashAlgorithm {
Sha256,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl HashAlgorithm {
@ -60,7 +62,7 @@ pub enum KeyAgreementProtocol {
Curve25519HkdfSha256,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl KeyAgreementProtocol {
@ -85,7 +87,7 @@ pub enum MessageAuthenticationCode {
HmacSha256,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl MessageAuthenticationCode {
@ -110,7 +112,7 @@ pub enum ShortAuthenticationString {
Emoji,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl ShortAuthenticationString {
@ -165,7 +167,7 @@ pub enum VerificationMethod {
ReciprocateV1,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl VerificationMethod {

View File

@ -6,6 +6,8 @@ use ruma_events_macros::EventContent;
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
#[cfg(feature = "unstable-pre-spec")]
use super::Relation;
@ -130,7 +132,7 @@ pub enum CancelCode {
MismatchedSas,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl CancelCode {
@ -153,10 +155,7 @@ mod tests {
#[test]
fn custom_cancel_codes_serialize_to_display_form() {
assert_eq!(
to_json_value(&CancelCode::_Custom("io.ruma.test".into())).unwrap(),
json!("io.ruma.test")
);
assert_eq!(to_json_value(CancelCode::from("io.ruma.test")).unwrap(), json!("io.ruma.test"));
}
#[test]
@ -168,7 +167,7 @@ mod tests {
fn custom_cancel_codes_deserialize_from_display_form() {
assert_eq!(
from_json_value::<CancelCode>(json!("io.ruma.test")).unwrap(),
CancelCode::_Custom("io.ruma.test".into())
)
"io.ruma.test".into()
);
}
}

View File

@ -399,3 +399,10 @@ where
{
serde_json::from_str(val.get()).map_err(E::custom)
}
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
// this crate. Used for string enums because their `_Custom` variant can't be
// truly private (only `#[doc(hidden)]`).
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -3,6 +3,8 @@
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
pub mod room;
pub mod server;
pub mod user;
@ -43,7 +45,7 @@ pub enum Recommendation {
Ban,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Recommendation {

View File

@ -7,6 +7,8 @@ use ruma_identifiers::{EventId, RoomId, RoomVersionId, UserId};
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.room.create` event.
///
/// This is the first event in a room and cannot be changed.
@ -72,9 +74,10 @@ pub enum RoomType {
/// Defines the room as a space.
#[ruma_enum(rename = "m.space")]
Space,
/// Defines the room as a custom type.
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl RoomType {

View File

@ -6,6 +6,8 @@ use ruma_events_macros::EventContent;
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.room.guest_access` event.
///
/// Controls whether guest users are allowed to join rooms.
@ -42,7 +44,7 @@ pub enum GuestAccess {
Forbidden,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl GuestAccess {

View File

@ -6,6 +6,8 @@ use ruma_events_macros::EventContent;
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.room.history_visibility` event.
///
/// This event controls whether a member of a room can see the events that happened in a room from
@ -58,7 +60,7 @@ pub enum HistoryVisibility {
WorldReadable,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl HistoryVisibility {

View File

@ -18,6 +18,8 @@ use std::borrow::Cow;
#[cfg(feature = "unstable-pre-spec")]
use std::collections::BTreeMap;
use crate::PrivOwnedStr;
/// The content of an `m.room.join_rules` event.
///
/// Describes how users are allowed to join the room.
@ -88,7 +90,7 @@ pub enum JoinRule {
#[doc(hidden)]
#[serde(skip_serializing)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl JoinRule {
@ -101,7 +103,7 @@ impl JoinRule {
#[cfg(feature = "unstable-pre-spec")]
JoinRule::Restricted(_) => "restricted",
JoinRule::Public => "public",
JoinRule::_Custom(rule) => rule,
JoinRule::_Custom(rule) => &rule.0,
}
}
}
@ -135,7 +137,7 @@ impl<'de> Deserialize<'de> for JoinRule {
#[cfg(feature = "unstable-pre-spec")]
"restricted" => from_raw_json_value(&json).map(Self::Restricted),
"public" => Ok(Self::Public),
_ => Ok(Self::_Custom(join_rule.into_owned())),
_ => Ok(Self::_Custom(PrivOwnedStr(join_rule.into()))),
}
}
}

View File

@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
use serde_json::value::RawValue as RawJsonValue;
use crate::{
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent,
EventContent, HasDeserializeFields, PrivOwnedStr, RedactContent, RedactedEventContent,
RedactedStateEventContent, StrippedStateEvent, SyncStateEvent,
};
@ -222,7 +222,7 @@ pub enum MembershipState {
Leave,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl MembershipState {

View File

@ -16,6 +16,7 @@ use serde_json::Value as JsonValue;
use super::{EncryptedFile, ImageInfo, ThumbnailInfo};
#[cfg(feature = "unstable-pre-spec")]
use crate::key::verification::VerificationMethod;
use crate::PrivOwnedStr;
mod content_serde;
pub mod feedback;
@ -738,7 +739,7 @@ pub enum ServerNoticeType {
UsageLimitReached,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl ServerNoticeType {
@ -763,7 +764,7 @@ pub enum LimitType {
MonthlyActiveUser,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl LimitType {
@ -785,7 +786,7 @@ pub enum MessageFormat {
Html,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl MessageFormat {

View File

@ -7,6 +7,8 @@ use ruma_identifiers::EventId;
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.room.message.feedback` event.
///
/// An acknowledgement of a message.
@ -47,7 +49,7 @@ pub enum FeedbackType {
Read,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl FeedbackType {

View File

@ -7,6 +7,8 @@ use ruma_identifiers::{DeviceId, EventEncryptionAlgorithm, RoomId};
use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.room_key_request` event.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
@ -59,7 +61,7 @@ pub enum Action {
CancelRequest,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Action {

View File

@ -9,6 +9,8 @@ use ruma_identifiers::DeviceId;
use ruma_serde::StringEnum;
use serde::{ser::SerializeStruct, Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.secret.request` event.
///
/// Event sent by a client to request a secret from another device or to cancel a previous request.
@ -57,7 +59,7 @@ pub enum RequestAction {
RequestCancellation,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl Serialize for RequestAction {
@ -78,7 +80,7 @@ impl Serialize for RequestAction {
st.end()
}
RequestAction::_Custom(custom) => {
st.serialize_field("action", custom)?;
st.serialize_field("action", &custom.0)?;
st.end()
}
}
@ -104,7 +106,7 @@ impl TryFrom<RequestActionJsonRepr> for RequestAction {
}
}
"request_cancellation" => Ok(RequestAction::RequestCancellation),
_ => Ok(RequestAction::_Custom(value.action)),
_ => Ok(RequestAction::_Custom(PrivOwnedStr(value.action.into()))),
}
}
}
@ -130,15 +132,17 @@ pub enum SecretName {
RecoveryKey,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
#[cfg(test)]
mod test {
use super::{RequestAction, SecretName, ToDeviceSecretRequestEventContent};
use matches::assert_matches;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
use super::{RequestAction, SecretName, ToDeviceSecretRequestEventContent};
use crate::PrivOwnedStr;
#[test]
fn secret_request_serialization() {
let content = ToDeviceSecretRequestEventContent::new(
@ -178,7 +182,7 @@ mod test {
#[test]
fn secret_custom_action_serialization() {
let content = ToDeviceSecretRequestEventContent::new(
RequestAction::_Custom("my_custom_action".into()),
RequestAction::_Custom(PrivOwnedStr("my_custom_action".into())),
"XYZxyz".into(),
"this_is_a_request_id".into(),
);
@ -291,7 +295,7 @@ mod test {
requesting_device_id,
request_id,
}
if action == RequestAction::_Custom("my_custom_action".into())
if action == RequestAction::_Custom(PrivOwnedStr("my_custom_action".into()))
&& requesting_device_id == "XYZxyz"
&& request_id == "this_is_a_request_id"
)

View File

@ -8,6 +8,8 @@ use ruma_events_macros::EventContent;
use ruma_serde::deserialize_cow_str;
use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// Map of tag names to tag info.
pub type Tags = BTreeMap<TagName, TagInfo>;
@ -94,7 +96,7 @@ pub enum TagName {
/// A custom tag
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl TagName {
@ -105,7 +107,7 @@ impl TagName {
pub fn display_name(&self) -> &str {
match self {
Self::_Custom(s) => {
let start = s.rfind('.').map(|p| p + 1).unwrap_or(0);
let start = s.0.rfind('.').map(|p| p + 1).unwrap_or(0);
&self.as_ref()[start..]
}
_ => &self.as_ref()[2..],
@ -120,7 +122,7 @@ impl AsRef<str> for TagName {
Self::LowPriority => "m.lowpriority",
Self::ServerNotice => "m.server_notice",
Self::User(tag) => tag.as_ref(),
Self::_Custom(s) => s,
Self::_Custom(s) => &s.0,
}
}
}
@ -135,7 +137,7 @@ where
"m.lowpriority" => Self::LowPriority,
"m.server_notice" => Self::ServerNotice,
s if s.starts_with("u.") => Self::User(UserTagName { name: s.into() }),
s => Self::_Custom(s.into()),
s => Self::_Custom(PrivOwnedStr(s.into())),
}
}
}

View File

@ -378,5 +378,4 @@ fn serialize_and_deserialize_from_display_form() {
serde_json_eq(EventType::Tag, json!("m.tag"));
serde_json_eq(EventType::Typing, json!("m.typing"));
serde_json_eq(EphemeralRoomEventType::Typing, json!("m.typing"));
serde_json_eq(EventType::_Custom("io.ruma.test".into()), json!("io.ruma.test"));
}

View File

@ -339,11 +339,8 @@ fn verification_request_serialization() {
let device_id: Box<DeviceId> = "XOWLHHFSWM".into();
let body = "@example:localhost is requesting to verify your key, ...".to_owned();
let methods = vec![
VerificationMethod::SasV1,
VerificationMethod::_Custom("m.qr_code.show.v1".to_owned()),
VerificationMethod::_Custom("m.reciprocate.v1".to_owned()),
];
let methods =
vec![VerificationMethod::SasV1, "m.qr_code.show.v1".into(), "m.reciprocate.v1".into()];
let json_data = json!({
"body": body,

View File

@ -13,3 +13,7 @@ event_enum! {
}
fn main() {}
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -13,3 +13,7 @@ event_enum! {
}
fn main() {}
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -24,3 +24,10 @@ pub mod openid;
pub mod query;
pub mod thirdparty;
pub mod transactions;
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
// this crate. Used for string enums because their `_Custom` variant can't be
// truly private (only `#[doc(hidden)]`).
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -4,6 +4,8 @@ use ruma_api::ruma_api;
use ruma_identifiers::{MxcUri, UserId};
use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
ruma_api! {
metadata: {
description: "Get profile information, such as a display name or avatar, for a given user.",
@ -82,7 +84,7 @@ pub enum ProfileField {
AvatarUrl,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl ProfileField {

View File

@ -4,6 +4,8 @@
use ruma_serde::{DeserializeFromCowStr, SerializeAsRefStr};
use ruma_serde_macros::{AsRefStr, DisplayAsRefStr, FromString};
use crate::PrivOwnedStr;
/// The basic key algorithms in the specification.
///
/// This type can hold an arbitrary string. To check for algorithms that are not available as a
@ -23,7 +25,7 @@ pub enum DeviceKeyAlgorithm {
SignedCurve25519,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
/// The signing key algorithms defined in the Matrix spec.
@ -39,7 +41,7 @@ pub enum SigningKeyAlgorithm {
Ed25519,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
/// An encryption algorithm to be used to encrypt messages sent to a room.
@ -59,7 +61,7 @@ pub enum EventEncryptionAlgorithm {
MegolmV1AesSha2,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
#[cfg(test)]
@ -94,9 +96,6 @@ mod tests {
EventEncryptionAlgorithm::OlmV1Curve25519AesSha2,
json!("m.olm.v1.curve25519-aes-sha2"),
);
serde_json_eq(
EventEncryptionAlgorithm::_Custom("io.ruma.test".into()),
json!("io.ruma.test"),
);
serde_json_eq(EventEncryptionAlgorithm::from("io.ruma.test"), json!("io.ruma.test"));
}
}

View File

@ -178,3 +178,10 @@ macro_rules! user_id {
$crate::_macros::user_id!($crate, $s)
};
}
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
// this crate. Used for string enums because their `_Custom` variant can't be
// truly private (only `#[doc(hidden)]`).
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -14,3 +14,10 @@ pub mod keys;
pub mod lookup;
pub mod status;
pub mod tos;
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
// this crate. Used for string enums because their `_Custom` variant can't be
// truly private (only `#[doc(hidden)]`).
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -2,6 +2,8 @@
use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
pub mod get_hash_parameters;
pub mod lookup_3pid;
@ -21,7 +23,7 @@ pub enum IdentifierHashingAlgorithm {
None,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
#[cfg(test)]

View File

@ -8,3 +8,10 @@
#![warn(missing_docs)]
pub mod send_event_notification;
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
// this crate. Used for string enums because their `_Custom` variant can't be
// truly private (only `#[doc(hidden)]`).
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PrivOwnedStr(Box<str>);

View File

@ -12,6 +12,8 @@ use ruma_serde::{Outgoing, StringEnum};
use serde::{Deserialize, Serialize};
use serde_json::value::RawValue as RawJsonValue;
use crate::PrivOwnedStr;
ruma_api! {
metadata: {
description: "Notify a push gateway about an event or update the number of unread notifications a user has",
@ -145,7 +147,7 @@ pub enum NotificationPriority {
Low,
#[doc(hidden)]
_Custom(String),
_Custom(PrivOwnedStr),
}
impl NotificationPriority {

View File

@ -32,7 +32,7 @@ pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> {
None => quote! { (inner) },
};
(Some(capture), quote! { inner })
(Some(capture), quote! { &inner.0 })
}
(Some(_), _) => {
return Err(syn::Error::new_spanned(

View File

@ -8,7 +8,6 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
let enum_name = &input.ident;
let rename_rule = get_rename_rule(input)?;
let mut fallback = None;
let mut fallback_ty = None;
let branches: Vec<_> = input
.variants
.iter()
@ -40,12 +39,13 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
None => quote! { 0 },
};
let ty = &fields[0].ty;
fallback = Some(quote! {
_ => #enum_name :: #variant_name { #member: s.into() }
_ => #enum_name::#variant_name {
#member: #ty(s.into()),
}
});
fallback_ty = Some(&fields[0].ty);
None
}
(Some(_), _) => {
@ -71,7 +71,7 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
impl<T> ::std::convert::From<T> for #enum_name
where
T: ::std::convert::AsRef<::std::primitive::str>
+ ::std::convert::Into<#fallback_ty>
+ ::std::convert::Into<::std::boxed::Box<::std::primitive::str>>
{
fn from(s: T) -> Self {
match s.as_ref() {

View File

@ -1,6 +1,9 @@
use ruma_serde::StringEnum;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
#[derive(Debug, PartialEq)]
struct PrivOwnedStr(Box<str>);
#[derive(Debug, PartialEq, StringEnum)]
#[ruma_enum(rename_all = "snake_case")]
enum MyEnum {
@ -9,7 +12,7 @@ enum MyEnum {
#[ruma_enum(rename = "m.third")]
Third,
HelloWorld,
_Custom(String),
_Custom(PrivOwnedStr),
}
#[test]
@ -18,7 +21,7 @@ fn as_ref_str() {
assert_eq!(MyEnum::Second.as_ref(), "second");
assert_eq!(MyEnum::Third.as_ref(), "m.third");
assert_eq!(MyEnum::HelloWorld.as_ref(), "hello_world");
assert_eq!(MyEnum::_Custom("HelloWorld".into()).as_ref(), "HelloWorld");
assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).as_ref(), "HelloWorld");
}
#[test]
@ -27,7 +30,7 @@ fn display() {
assert_eq!(MyEnum::Second.to_string(), "second");
assert_eq!(MyEnum::Third.to_string(), "m.third");
assert_eq!(MyEnum::HelloWorld.to_string(), "hello_world");
assert_eq!(MyEnum::_Custom("HelloWorld".into()).to_string(), "HelloWorld");
assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).to_string(), "HelloWorld");
}
#[test]
@ -36,14 +39,17 @@ fn from_string() {
assert_eq!(MyEnum::from("second"), MyEnum::Second);
assert_eq!(MyEnum::from("m.third"), MyEnum::Third);
assert_eq!(MyEnum::from("hello_world"), MyEnum::HelloWorld);
assert_eq!(MyEnum::from("HelloWorld"), MyEnum::_Custom("HelloWorld".into()));
assert_eq!(MyEnum::from("HelloWorld"), MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())));
}
#[test]
fn serialize() {
assert_eq!(to_json_value(MyEnum::First).unwrap(), json!("first"));
assert_eq!(to_json_value(MyEnum::HelloWorld).unwrap(), json!("hello_world"));
assert_eq!(to_json_value(MyEnum::_Custom("\\\n\\".into())).unwrap(), json!("\\\n\\"));
assert_eq!(
to_json_value(MyEnum::_Custom(PrivOwnedStr("\\\n\\".into()))).unwrap(),
json!("\\\n\\")
);
}
#[test]
@ -52,6 +58,6 @@ fn deserialize() {
assert_eq!(from_json_value::<MyEnum>(json!("hello_world")).unwrap(), MyEnum::HelloWorld);
assert_eq!(
from_json_value::<MyEnum>(json!("\\\n\\")).unwrap(),
MyEnum::_Custom("\\\n\\".into())
MyEnum::_Custom(PrivOwnedStr("\\\n\\".into()))
);
}