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::{Deserialize, Serialize};
use serde_json::{from_slice as from_json_slice, Value as JsonValue}; use serde_json::{from_slice as from_json_slice, Value as JsonValue};
use crate::PrivOwnedStr;
/// Deserialize and Serialize implementations for ErrorKind. /// Deserialize and Serialize implementations for ErrorKind.
/// Separate module because it's a lot of code. /// Separate module because it's a lot of code.
mod kind_serde; mod kind_serde;
@ -18,7 +20,7 @@ mod kind_serde;
/// An enum for the error kind. /// An enum for the error kind.
/// ///
/// Items may contain additional information. /// Items may contain additional information.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive] #[non_exhaustive]
pub enum ErrorKind { pub enum ErrorKind {
/// M_FORBIDDEN /// M_FORBIDDEN
@ -135,9 +137,13 @@ pub enum ErrorKind {
CannotLeaveServerNoticeRoom, CannotLeaveServerNoticeRoom,
#[doc(hidden)] #[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 { impl AsRef<str> for ErrorKind {
fn as_ref(&self) -> &str { fn as_ref(&self) -> &str {
match self { match self {
@ -173,7 +179,7 @@ impl AsRef<str> for ErrorKind {
Self::Exclusive => "M_EXCLUSIVE", Self::Exclusive => "M_EXCLUSIVE",
Self::ResourceLimitExceeded { .. } => "M_RESOURCE_LIMIT_EXCEEDED", Self::ResourceLimitExceeded { .. } => "M_RESOURCE_LIMIT_EXCEEDED",
Self::CannotLeaveServerNoticeRoom => "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM", 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 serde_json::from_value as from_json_value;
use super::ErrorKind; use super::{ErrorKind, Extra};
use crate::PrivOwnedStr;
enum Field<'de> { enum Field<'de> {
ErrCode, ErrCode,
@ -147,6 +148,8 @@ impl<'de> Visitor<'de> for ErrorKindVisitor {
} }
let errcode = errcode.ok_or_else(|| de::Error::missing_field("errcode"))?; let errcode = errcode.ok_or_else(|| de::Error::missing_field("errcode"))?;
let extra = Extra(extra);
Ok(match errcode { Ok(match errcode {
ErrCode::Forbidden => ErrorKind::Forbidden, ErrCode::Forbidden => ErrorKind::Forbidden,
ErrCode::UnknownToken => ErrorKind::UnknownToken { ErrCode::UnknownToken => ErrorKind::UnknownToken {
@ -243,7 +246,7 @@ enum ErrCode {
Exclusive, Exclusive,
ResourceLimitExceeded, ResourceLimitExceeded,
CannotLeaveServerNoticeRoom, CannotLeaveServerNoticeRoom,
_Custom(String), _Custom(PrivOwnedStr),
} }
impl<'de> Deserialize<'de> for ErrorKind { impl<'de> Deserialize<'de> for ErrorKind {
@ -279,7 +282,7 @@ impl Serialize for ErrorKind {
st.serialize_entry("admin_contact", admin_contact)?; st.serialize_entry("admin_contact", admin_contact)?;
} }
Self::_Custom { extra, .. } => { Self::_Custom { extra, .. } => {
for (k, v) in extra { for (k, v) in &extra.0 {
st.serialize_entry(k, v)?; st.serialize_entry(k, v)?;
} }
} }

View File

@ -13,3 +13,10 @@ pub mod r0;
pub mod unversioned; pub mod unversioned;
pub use error::Error; 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 ruma_serde::{Outgoing, StringEnum};
use serde::Serialize; use serde::Serialize;
use crate::PrivOwnedStr;
/// Additional authentication information for requestToken endpoints. /// Additional authentication information for requestToken endpoints.
#[derive(Clone, Debug, Outgoing, Serialize)] #[derive(Clone, Debug, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
@ -58,7 +60,7 @@ pub enum ThirdPartyIdRemovalStatus {
Success, Success,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl ThirdPartyIdRemovalStatus { 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 iter::{CapabilitiesIter, CapabilityRef};
use crate::PrivOwnedStr;
pub mod get_capabilities; pub mod get_capabilities;
pub mod iter; pub mod iter;
@ -176,7 +178,7 @@ pub enum RoomVersionStability {
Unstable, Unstable,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl RoomVersionStability { impl RoomVersionStability {

View File

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

View File

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

View File

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

View File

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

View File

@ -8,6 +8,8 @@ pub mod upgrade_room;
use ruma_serde::StringEnum; use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
/// Whether or not a newly created room will be listed in the room directory. /// 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 /// 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, Private,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl Visibility { impl Visibility {

View File

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

View File

@ -9,7 +9,10 @@ use ruma_identifiers::{EventId, MxcUri, RoomId, UserId};
use ruma_serde::{Outgoing, Raw, StringEnum}; use ruma_serde::{Outgoing, Raw, StringEnum};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::r0::filter::{IncomingRoomEventFilter, RoomEventFilter}; use crate::{
r0::filter::{IncomingRoomEventFilter, RoomEventFilter},
PrivOwnedStr,
};
ruma_api! { ruma_api! {
metadata: { metadata: {
@ -252,7 +255,7 @@ pub enum GroupingKey {
Sender, Sender,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl GroupingKey { impl GroupingKey {
@ -304,7 +307,7 @@ pub enum SearchKeys {
ContentTopic, ContentTopic,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl SearchKeys { impl SearchKeys {
@ -327,7 +330,7 @@ pub enum OrderBy {
Rank, Rank,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
/// Categories of events that can be searched for. /// 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::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value as JsonValue; use serde_json::Value as JsonValue;
#[cfg(feature = "unstable-pre-spec")]
use crate::PrivOwnedStr;
ruma_api! { ruma_api! {
metadata: { 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.", 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. /// A custom brand.
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
/// A custom login payload. /// 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, 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; pub mod get_uiaa_fallback_page;
mod user_serde; mod user_serde;
@ -85,7 +88,7 @@ impl<'a> AuthData<'a> {
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
Self::RegistrationToken(_) => Some(AuthType::RegistrationToken), Self::RegistrationToken(_) => Some(AuthType::RegistrationToken),
Self::FallbackAcknowledgement(_) => None, 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")] #[cfg(feature = "unstable-pre-spec")]
Self::RegistrationToken(_) => Some(AuthType::RegistrationToken), Self::RegistrationToken(_) => Some(AuthType::RegistrationToken),
Self::FallbackAcknowledgement(_) => None, 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, RegistrationToken,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
/// Data for password-based UIAA flow. /// Data for password-based UIAA flow.

View File

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

View File

@ -17,3 +17,10 @@ mod time;
pub mod to_device; pub mod to_device;
pub use time::{MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch}; 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 ruma_serde::StringEnum;
use crate::PrivOwnedStr;
/// A description of a user's connectivity and availability for chat. /// 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 /// 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, Unavailable,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl Default for PresenceState { impl Default for PresenceState {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,8 @@ use ruma_events_macros::EventContent;
use ruma_serde::StringEnum; use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.call.hangup` event. /// 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 /// 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, InviteTimeout,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl Reason { impl Reason {

View File

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

View File

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

View File

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

View File

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

View File

@ -6,6 +6,8 @@ use ruma_events_macros::EventContent;
use ruma_serde::StringEnum; use ruma_serde::StringEnum;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.room.history_visibility` event. /// 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 /// 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, WorldReadable,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl HistoryVisibility { impl HistoryVisibility {

View File

@ -18,6 +18,8 @@ use std::borrow::Cow;
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
use std::collections::BTreeMap; use std::collections::BTreeMap;
use crate::PrivOwnedStr;
/// The content of an `m.room.join_rules` event. /// The content of an `m.room.join_rules` event.
/// ///
/// Describes how users are allowed to join the room. /// Describes how users are allowed to join the room.
@ -88,7 +90,7 @@ pub enum JoinRule {
#[doc(hidden)] #[doc(hidden)]
#[serde(skip_serializing)] #[serde(skip_serializing)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl JoinRule { impl JoinRule {
@ -101,7 +103,7 @@ impl JoinRule {
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
JoinRule::Restricted(_) => "restricted", JoinRule::Restricted(_) => "restricted",
JoinRule::Public => "public", 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")] #[cfg(feature = "unstable-pre-spec")]
"restricted" => from_raw_json_value(&json).map(Self::Restricted), "restricted" => from_raw_json_value(&json).map(Self::Restricted),
"public" => Ok(Self::Public), "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 serde_json::value::RawValue as RawJsonValue;
use crate::{ use crate::{
EventContent, HasDeserializeFields, RedactContent, RedactedEventContent, EventContent, HasDeserializeFields, PrivOwnedStr, RedactContent, RedactedEventContent,
RedactedStateEventContent, StrippedStateEvent, SyncStateEvent, RedactedStateEventContent, StrippedStateEvent, SyncStateEvent,
}; };
@ -222,7 +222,7 @@ pub enum MembershipState {
Leave, Leave,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl MembershipState { impl MembershipState {

View File

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

View File

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

View File

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

View File

@ -9,6 +9,8 @@ use ruma_identifiers::DeviceId;
use ruma_serde::StringEnum; use ruma_serde::StringEnum;
use serde::{ser::SerializeStruct, Deserialize, Serialize}; use serde::{ser::SerializeStruct, Deserialize, Serialize};
use crate::PrivOwnedStr;
/// The content of an `m.secret.request` event. /// 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. /// 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, RequestCancellation,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl Serialize for RequestAction { impl Serialize for RequestAction {
@ -78,7 +80,7 @@ impl Serialize for RequestAction {
st.end() st.end()
} }
RequestAction::_Custom(custom) => { RequestAction::_Custom(custom) => {
st.serialize_field("action", custom)?; st.serialize_field("action", &custom.0)?;
st.end() st.end()
} }
} }
@ -104,7 +106,7 @@ impl TryFrom<RequestActionJsonRepr> for RequestAction {
} }
} }
"request_cancellation" => Ok(RequestAction::RequestCancellation), "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, RecoveryKey,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{RequestAction, SecretName, ToDeviceSecretRequestEventContent};
use matches::assert_matches; use matches::assert_matches;
use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; 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] #[test]
fn secret_request_serialization() { fn secret_request_serialization() {
let content = ToDeviceSecretRequestEventContent::new( let content = ToDeviceSecretRequestEventContent::new(
@ -178,7 +182,7 @@ mod test {
#[test] #[test]
fn secret_custom_action_serialization() { fn secret_custom_action_serialization() {
let content = ToDeviceSecretRequestEventContent::new( let content = ToDeviceSecretRequestEventContent::new(
RequestAction::_Custom("my_custom_action".into()), RequestAction::_Custom(PrivOwnedStr("my_custom_action".into())),
"XYZxyz".into(), "XYZxyz".into(),
"this_is_a_request_id".into(), "this_is_a_request_id".into(),
); );
@ -291,9 +295,9 @@ mod test {
requesting_device_id, requesting_device_id,
request_id, request_id,
} }
if action == RequestAction::_Custom("my_custom_action".into()) if action == RequestAction::_Custom(PrivOwnedStr("my_custom_action".into()))
&& requesting_device_id == "XYZxyz" && requesting_device_id == "XYZxyz"
&& request_id == "this_is_a_request_id" && 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 ruma_serde::deserialize_cow_str;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::PrivOwnedStr;
/// Map of tag names to tag info. /// Map of tag names to tag info.
pub type Tags = BTreeMap<TagName, TagInfo>; pub type Tags = BTreeMap<TagName, TagInfo>;
@ -94,7 +96,7 @@ pub enum TagName {
/// A custom tag /// A custom tag
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl TagName { impl TagName {
@ -105,7 +107,7 @@ impl TagName {
pub fn display_name(&self) -> &str { pub fn display_name(&self) -> &str {
match self { match self {
Self::_Custom(s) => { 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()[start..]
} }
_ => &self.as_ref()[2..], _ => &self.as_ref()[2..],
@ -120,7 +122,7 @@ impl AsRef<str> for TagName {
Self::LowPriority => "m.lowpriority", Self::LowPriority => "m.lowpriority",
Self::ServerNotice => "m.server_notice", Self::ServerNotice => "m.server_notice",
Self::User(tag) => tag.as_ref(), 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.lowpriority" => Self::LowPriority,
"m.server_notice" => Self::ServerNotice, "m.server_notice" => Self::ServerNotice,
s if s.starts_with("u.") => Self::User(UserTagName { name: s.into() }), 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::Tag, json!("m.tag"));
serde_json_eq(EventType::Typing, json!("m.typing")); serde_json_eq(EventType::Typing, json!("m.typing"));
serde_json_eq(EphemeralRoomEventType::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 device_id: Box<DeviceId> = "XOWLHHFSWM".into();
let body = "@example:localhost is requesting to verify your key, ...".to_owned(); let body = "@example:localhost is requesting to verify your key, ...".to_owned();
let methods = vec![ let methods =
VerificationMethod::SasV1, vec![VerificationMethod::SasV1, "m.qr_code.show.v1".into(), "m.reciprocate.v1".into()];
VerificationMethod::_Custom("m.qr_code.show.v1".to_owned()),
VerificationMethod::_Custom("m.reciprocate.v1".to_owned()),
];
let json_data = json!({ let json_data = json!({
"body": body, "body": body,

View File

@ -13,3 +13,7 @@ event_enum! {
} }
fn main() {} 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() {} 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 query;
pub mod thirdparty; pub mod thirdparty;
pub mod transactions; 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_identifiers::{MxcUri, UserId};
use ruma_serde::StringEnum; use ruma_serde::StringEnum;
use crate::PrivOwnedStr;
ruma_api! { ruma_api! {
metadata: { metadata: {
description: "Get profile information, such as a display name or avatar, for a given user.", description: "Get profile information, such as a display name or avatar, for a given user.",
@ -82,7 +84,7 @@ pub enum ProfileField {
AvatarUrl, AvatarUrl,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl ProfileField { impl ProfileField {

View File

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

View File

@ -178,3 +178,10 @@ macro_rules! user_id {
$crate::_macros::user_id!($crate, $s) $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 lookup;
pub mod status; pub mod status;
pub mod tos; 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 ruma_serde::StringEnum;
use crate::PrivOwnedStr;
pub mod get_hash_parameters; pub mod get_hash_parameters;
pub mod lookup_3pid; pub mod lookup_3pid;
@ -21,7 +23,7 @@ pub enum IdentifierHashingAlgorithm {
None, None,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
#[cfg(test)] #[cfg(test)]

View File

@ -8,3 +8,10 @@
#![warn(missing_docs)] #![warn(missing_docs)]
pub mod send_event_notification; 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::{Deserialize, Serialize};
use serde_json::value::RawValue as RawJsonValue; use serde_json::value::RawValue as RawJsonValue;
use crate::PrivOwnedStr;
ruma_api! { ruma_api! {
metadata: { metadata: {
description: "Notify a push gateway about an event or update the number of unread notifications a user has", 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, Low,
#[doc(hidden)] #[doc(hidden)]
_Custom(String), _Custom(PrivOwnedStr),
} }
impl NotificationPriority { impl NotificationPriority {

View File

@ -32,7 +32,7 @@ pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> {
None => quote! { (inner) }, None => quote! { (inner) },
}; };
(Some(capture), quote! { inner }) (Some(capture), quote! { &inner.0 })
} }
(Some(_), _) => { (Some(_), _) => {
return Err(syn::Error::new_spanned( 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 enum_name = &input.ident;
let rename_rule = get_rename_rule(input)?; let rename_rule = get_rename_rule(input)?;
let mut fallback = None; let mut fallback = None;
let mut fallback_ty = None;
let branches: Vec<_> = input let branches: Vec<_> = input
.variants .variants
.iter() .iter()
@ -40,12 +39,13 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
None => quote! { 0 }, None => quote! { 0 },
}; };
let ty = &fields[0].ty;
fallback = Some(quote! { 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 None
} }
(Some(_), _) => { (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 impl<T> ::std::convert::From<T> for #enum_name
where where
T: ::std::convert::AsRef<::std::primitive::str> 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 { fn from(s: T) -> Self {
match s.as_ref() { match s.as_ref() {

View File

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