Replace compat feature with more fine-grained compat-* features
… and document them.
This commit is contained in:
parent
57b7b2d0f5
commit
4c85fe9c78
@ -16,7 +16,23 @@ all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[features]
|
||||
compat = []
|
||||
# OutgoingRequest and IncomingResponse implementations
|
||||
client = []
|
||||
# IncomingRequest and OutgoingResponse implementations
|
||||
server = []
|
||||
|
||||
# Allow some mandatory fields in requests / responses to be missing, defaulting
|
||||
# them to an empty string in deserialization.
|
||||
compat-empty-string-null = []
|
||||
|
||||
# Unset avatars by sending an empty string, same as what Element Web does, c.f.
|
||||
# https://github.com/matrix-org/matrix-spec/issues/378#issuecomment-1055831264
|
||||
compat-unset-avatar = []
|
||||
|
||||
# Always serialize the threepids response field in `get_3pids::v3::Response`,
|
||||
# even if its value is an empty list.
|
||||
compat-get-3pids = []
|
||||
|
||||
unstable-exhaustive-types = ["ruma-common/unstable-exhaustive-types"]
|
||||
unstable-msc2246 = []
|
||||
unstable-msc2666 = []
|
||||
@ -27,8 +43,6 @@ unstable-msc2965 = []
|
||||
unstable-msc2967 = []
|
||||
unstable-msc3488 = []
|
||||
unstable-msc3575 = []
|
||||
client = []
|
||||
server = []
|
||||
|
||||
[dependencies]
|
||||
assign = { workspace = true }
|
||||
|
@ -33,8 +33,14 @@ pub mod v3 {
|
||||
pub struct Response {
|
||||
/// A list of third party identifiers the homeserver has associated with the user's
|
||||
/// account.
|
||||
///
|
||||
/// If the `compat-get-3pids` feature is enabled, this field will always be serialized,
|
||||
/// even if its value is an empty list.
|
||||
#[serde(default)]
|
||||
#[cfg_attr(not(feature = "compat"), serde(skip_serializing_if = "Vec::is_empty"))]
|
||||
#[cfg_attr(
|
||||
not(feature = "compat-get-3pids"),
|
||||
serde(skip_serializing_if = "Vec::is_empty")
|
||||
)]
|
||||
pub threepids: Vec<ThirdPartyIdentifier>,
|
||||
}
|
||||
|
||||
|
@ -57,11 +57,11 @@ pub mod v3 {
|
||||
///
|
||||
/// If omitted, verification happens without client.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub submit_url: Option<String>,
|
||||
|
@ -60,11 +60,11 @@ pub mod v3 {
|
||||
///
|
||||
/// If omitted, verification happens without client.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub submit_url: Option<String>,
|
||||
|
@ -57,11 +57,11 @@ pub mod v3 {
|
||||
///
|
||||
/// If omitted, verification happens without client.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub submit_url: Option<String>,
|
||||
|
@ -53,11 +53,11 @@ pub mod v3 {
|
||||
///
|
||||
/// If omitted, verification happens without client.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub submit_url: Option<String>,
|
||||
|
@ -57,11 +57,11 @@ pub mod v3 {
|
||||
///
|
||||
/// If omitted, verification happens without client.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub submit_url: Option<String>,
|
||||
|
@ -60,11 +60,11 @@ pub mod v3 {
|
||||
///
|
||||
/// If omitted, verification happens without client.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub submit_url: Option<String>,
|
||||
|
@ -66,11 +66,11 @@ pub mod v3 {
|
||||
|
||||
/// The mxc avatar url of the user.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
@ -103,7 +103,7 @@ pub mod v3 {
|
||||
Some(mxc_uri!("mxc://localhost/wefuiwegh8742w"))
|
||||
);
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
#[cfg(feature = "compat-empty-string-null")]
|
||||
{
|
||||
let member = from_json_value::<RoomMember>(json!({
|
||||
"display_name": "alice",
|
||||
|
@ -36,11 +36,11 @@ pub mod v3 {
|
||||
pub struct Response {
|
||||
/// The user's avatar URL, if set.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -36,11 +36,11 @@ pub mod v3 {
|
||||
pub struct Response {
|
||||
/// The user's avatar URL, if set.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -33,18 +33,24 @@ pub mod v3 {
|
||||
///
|
||||
/// `None` is used to unset the avatar.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
///
|
||||
/// If you active the `compat-unset-avatar` feature, this field being `None` will result
|
||||
/// in an empty string in serialization, which is the same thing Element Web does (c.f.
|
||||
/// <https://github.com/matrix-org/matrix-spec/issues/378#issuecomment-1055831264>).
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
serde(
|
||||
default,
|
||||
deserialize_with = "ruma_common::serde::empty_string_as_none",
|
||||
// https://github.com/matrix-org/matrix-spec/issues/378
|
||||
serialize_with = "ruma_common::serde::none_as_empty_string"
|
||||
)
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "compat-unset-avatar",
|
||||
serde(serialize_with = "ruma_common::serde::none_as_empty_string")
|
||||
)]
|
||||
#[cfg_attr(
|
||||
not(feature = "compat-unset-avatar"),
|
||||
serde(skip_serializing_if = "Option::is_none")
|
||||
)]
|
||||
#[cfg_attr(not(feature = "compat"), serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
||||
/// The [BlurHash](https://blurha.sh) for the avatar pointed to by `avatar_url`.
|
||||
@ -100,7 +106,7 @@ pub mod v3 {
|
||||
assert_eq!(req.user_id, "@foo:bar.org");
|
||||
assert_eq!(req.avatar_url, None);
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
#[cfg(feature = "compat-empty-string-null")]
|
||||
{
|
||||
let req = Request::try_from_http_request(
|
||||
http::Request::builder()
|
||||
|
@ -460,11 +460,11 @@ pub mod v3 {
|
||||
pub struct UserProfile {
|
||||
/// The user's avatar URL, if set.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -27,7 +27,7 @@ pub struct SpaceHierarchyRoomsChunk {
|
||||
/// The canonical alias of the room, if any.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub canonical_alias: Option<OwnedRoomAliasId>,
|
||||
@ -56,11 +56,11 @@ pub struct SpaceHierarchyRoomsChunk {
|
||||
|
||||
/// The URL for the room's avatar, if one is set.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will result
|
||||
/// in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty string in
|
||||
/// JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -91,11 +91,11 @@ pub mod v3 {
|
||||
|
||||
/// The avatar url, as an MXC, if one exists.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -23,7 +23,6 @@ server = []
|
||||
|
||||
api = ["dep:http"]
|
||||
canonical-json = []
|
||||
compat = ["ruma-macros/compat", "ruma-identifiers-validation/compat"]
|
||||
events = []
|
||||
js = ["dep:js-sys", "getrandom?/js", "uuid?/js"]
|
||||
markdown = ["pulldown-cmark"]
|
||||
@ -54,6 +53,25 @@ unstable-pdu = []
|
||||
unstable-sanitize = ["dep:html5ever", "dep:phf"]
|
||||
unstable-unspecified = []
|
||||
|
||||
# Don't validate the version part in `KeyId`.
|
||||
compat-key-id = ["ruma-identifiers-validation/compat-key-id"]
|
||||
|
||||
# Allow some user IDs that are invalid even with the specified historical
|
||||
# user ID scheme.
|
||||
compat-user-id = ["ruma-identifiers-validation/compat-user-id"]
|
||||
|
||||
# Allow some mandatory fields to be missing, defaulting them to an empty string
|
||||
# in deserialization.
|
||||
compat-empty-string-null = []
|
||||
|
||||
# Allow certain fields to be `null` for compatibility, treating that the same as
|
||||
# the field being absent.
|
||||
compat-null = []
|
||||
|
||||
# Allow certain fields to be absent even though the spec marks them as
|
||||
# mandatory. Deserialization will yield a default value like an empty string.
|
||||
compat-optional = []
|
||||
|
||||
[dependencies]
|
||||
base64 = { workspace = true }
|
||||
bytes = "1.0.1"
|
||||
|
@ -20,7 +20,7 @@ pub struct PublicRoomsChunk {
|
||||
/// The canonical alias of the room, if any.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "crate::serde::empty_string_as_none")
|
||||
)]
|
||||
pub canonical_alias: Option<OwnedRoomAliasId>,
|
||||
@ -49,11 +49,11 @@ pub struct PublicRoomsChunk {
|
||||
|
||||
/// The URL for the room's avatar, if one is set.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will result
|
||||
/// in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty string in
|
||||
/// JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "crate::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
@ -120,8 +120,11 @@ pub struct Filter {
|
||||
/// The room types to include in the results.
|
||||
///
|
||||
/// Includes all room types if it is empty.
|
||||
///
|
||||
/// If the `compat-null` feature is enabled, a `null` value is allowed in deserialization, and
|
||||
/// treated the same way as an empty list.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
#[cfg_attr(feature = "compat", serde(deserialize_with = "crate::serde::none_as_default"))]
|
||||
#[cfg_attr(feature = "compat-null", serde(deserialize_with = "crate::serde::none_as_default"))]
|
||||
pub room_types: Vec<RoomTypeFilter>,
|
||||
}
|
||||
|
||||
|
@ -42,11 +42,11 @@ impl Serialize for PresenceEvent {
|
||||
pub struct PresenceEventContent {
|
||||
/// The current avatar URL for this user.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will result
|
||||
/// in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty string in
|
||||
/// JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "crate::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
@ -141,7 +141,7 @@ mod tests {
|
||||
assert_eq!(ev.content.status_msg.as_deref(), Some("Making cupcakes"));
|
||||
assert_eq!(ev.sender, "@example:localhost");
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
#[cfg(feature = "compat-empty-string-null")]
|
||||
{
|
||||
let json = json!({
|
||||
"content": {
|
||||
|
@ -57,11 +57,11 @@ pub use self::change::{Change, MembershipChange, MembershipDetails};
|
||||
pub struct RoomMemberEventContent {
|
||||
/// The avatar URL for this user, if any.
|
||||
///
|
||||
/// This is added by the homeserver. If you activate the `compat` feature, this field being an
|
||||
/// empty string in JSON will result in `None` here during deserialization.
|
||||
/// This is added by the homeserver. If you activate the `compat-empty-string-null` feature,
|
||||
/// this field being an empty string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "crate::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -20,23 +20,23 @@ use crate::serde::Base64;
|
||||
pub struct RoomThirdPartyInviteEventContent {
|
||||
/// A user-readable string which represents the user who has been invited.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being absent in JSON will result in an
|
||||
/// empty string here during deserialization.
|
||||
#[cfg_attr(feature = "compat", serde(default))]
|
||||
/// If the `compat-optional` feature is enabled, this field being absent in JSON will result
|
||||
/// in an empty string instead of an error when deserializing.
|
||||
#[cfg_attr(feature = "compat-optional", serde(default))]
|
||||
pub display_name: String,
|
||||
|
||||
/// A URL which can be fetched to validate whether the key has been revoked.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being absent in JSON will result in an
|
||||
/// empty string here during deserialization.
|
||||
#[cfg_attr(feature = "compat", serde(default))]
|
||||
/// If the `compat-optional` feature is enabled, this field being absent in JSON will result
|
||||
/// in an empty string instead of an error when deserializing.
|
||||
#[cfg_attr(feature = "compat-optional", serde(default))]
|
||||
pub key_validity_url: String,
|
||||
|
||||
/// A base64-encoded Ed25519 key with which the token must be signed.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being absent in JSON will result in an
|
||||
/// empty string here during deserialization.
|
||||
#[cfg_attr(feature = "compat", serde(default = "Base64::empty"))]
|
||||
/// If the `compat-optional` feature is enabled, this field being absent in JSON will result
|
||||
/// in an empty string instead of an error when deserializing.
|
||||
#[cfg_attr(feature = "compat-optional", serde(default = "Base64::empty"))]
|
||||
pub public_key: Base64,
|
||||
|
||||
/// Keys with which the token may be signed.
|
||||
|
@ -28,9 +28,9 @@ use crate::{
|
||||
pub struct RoomTombstoneEventContent {
|
||||
/// A server-defined message.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being absent in JSON will result in an
|
||||
/// empty string here during deserialization.
|
||||
#[cfg_attr(feature = "compat", serde(default))]
|
||||
/// If the `compat-optional` feature is enabled, this field being absent in JSON will result
|
||||
/// in an empty string instead of an error when deserializing.
|
||||
#[cfg_attr(feature = "compat-optional", serde(default))]
|
||||
pub body: String,
|
||||
|
||||
/// The new room the client should be visiting.
|
||||
|
@ -188,7 +188,7 @@ mod tests {
|
||||
assert!(!user_id.is_historical());
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "compat"))]
|
||||
#[cfg(not(feature = "compat-user-id"))]
|
||||
#[test]
|
||||
fn invalid_user_id() {
|
||||
let localpart = "τ";
|
||||
@ -303,7 +303,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "compat"))]
|
||||
#[cfg(not(feature = "compat-user-id"))]
|
||||
fn invalid_characters_in_user_id_localpart() {
|
||||
assert_eq!(
|
||||
<&UserId>::try_from("@te\nst:example.com").unwrap_err(),
|
||||
|
@ -25,9 +25,9 @@ pub struct Protocol {
|
||||
|
||||
/// A content URI representing an icon for the third party protocol.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being absent in JSON will result in an
|
||||
/// empty string here during deserialization.
|
||||
#[cfg_attr(feature = "compat", serde(default))]
|
||||
/// If the `compat-optional` feature is enabled, this field being absent in JSON will result
|
||||
/// in an empty string instead of an error when deserializing.
|
||||
#[cfg_attr(feature = "compat-optional", serde(default))]
|
||||
pub icon: String,
|
||||
|
||||
/// The type definitions for the fields defined in `user_fields` and `location_fields`.
|
||||
|
@ -16,7 +16,10 @@ all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[features]
|
||||
compat = []
|
||||
# Allow some mandatory fields in requests / responses to be missing, defaulting
|
||||
# them to an empty string in deserialization.
|
||||
compat-empty-string-null = []
|
||||
|
||||
client = []
|
||||
server = []
|
||||
unstable-exhaustive-types = []
|
||||
|
@ -48,11 +48,11 @@ pub mod v1 {
|
||||
|
||||
/// Avatar URL for the user's avatar.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will
|
||||
/// result in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -17,9 +17,12 @@ pub mod get_hierarchy;
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub struct SpaceHierarchyParentSummary {
|
||||
/// The canonical alias of the room, if any.
|
||||
///
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty
|
||||
/// string in JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub canonical_alias: Option<OwnedRoomAliasId>,
|
||||
@ -48,11 +51,11 @@ pub struct SpaceHierarchyParentSummary {
|
||||
|
||||
/// The URL for the room's avatar, if one is set.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will result
|
||||
/// in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty string in
|
||||
/// JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
@ -147,9 +150,12 @@ impl From<SpaceHierarchyParentSummaryInit> for SpaceHierarchyParentSummary {
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub struct SpaceHierarchyChildSummary {
|
||||
/// The canonical alias of the room, if any.
|
||||
///
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty string in
|
||||
/// JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub canonical_alias: Option<OwnedRoomAliasId>,
|
||||
@ -178,11 +184,11 @@ pub struct SpaceHierarchyChildSummary {
|
||||
|
||||
/// The URL for the room's avatar, if one is set.
|
||||
///
|
||||
/// If you activate the `compat` feature, this field being an empty string in JSON will result
|
||||
/// in `None` here during deserialization.
|
||||
/// If you activate the `compat-empty-string-null` feature, this field being an empty string in
|
||||
/// JSON will result in `None` here during deserialization.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[cfg_attr(
|
||||
feature = "compat",
|
||||
feature = "compat-empty-string-null",
|
||||
serde(default, deserialize_with = "ruma_common::serde::empty_string_as_none")
|
||||
)]
|
||||
pub avatar_url: Option<OwnedMxcUri>,
|
||||
|
@ -12,7 +12,11 @@ rust-version = "1.64"
|
||||
all-features = true
|
||||
|
||||
[features]
|
||||
compat = []
|
||||
# Don't validate the version part in `key_id::validate`.
|
||||
compat-key-id = []
|
||||
# Allow some user IDs that are invalid even with the specified historical
|
||||
# user ID scheme.
|
||||
compat-user-id = []
|
||||
|
||||
[dependencies]
|
||||
js_int = { workspace = true }
|
||||
|
@ -6,13 +6,13 @@ pub fn validate(s: &str) -> Result<NonZeroU8, Error> {
|
||||
let colon_idx =
|
||||
NonZeroU8::new(s.find(':').ok_or(Error::MissingColon)? as u8).ok_or(Error::MissingColon)?;
|
||||
|
||||
#[cfg(not(feature = "compat"))]
|
||||
#[cfg(not(feature = "compat-key-id"))]
|
||||
validate_version(&s[colon_idx.get() as usize + 1..])?;
|
||||
|
||||
Ok(colon_idx)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "compat"))]
|
||||
#[cfg(not(feature = "compat-key-id"))]
|
||||
fn validate_version(version: &str) -> Result<(), Error> {
|
||||
if version.is_empty() {
|
||||
return Err(Error::Empty);
|
||||
|
@ -27,13 +27,13 @@ pub fn localpart_is_fully_conforming(localpart: &str) -> Result<bool, Error> {
|
||||
// If it's not fully conforming, check if it contains characters that are also disallowed
|
||||
// for historical user IDs. If there are, return an error.
|
||||
// See https://spec.matrix.org/latest/appendices/#historical-user-ids
|
||||
#[cfg(not(feature = "compat"))]
|
||||
#[cfg(not(feature = "compat-user-id"))]
|
||||
let is_invalid = localpart.bytes().any(|b| b < 0x21 || b == b':' || b > 0x7E);
|
||||
|
||||
// In compat mode, allow anything except `:` to match Synapse. The `:` check is only needed
|
||||
// because this function can be called through `UserId::parse_with_servername`, otherwise
|
||||
// it would be impossible for the input to contain a `:`.
|
||||
#[cfg(feature = "compat")]
|
||||
#[cfg(feature = "compat-user-id")]
|
||||
let is_invalid = localpart.as_bytes().contains(&b':');
|
||||
|
||||
if is_invalid {
|
||||
|
@ -14,9 +14,6 @@ rust-version = "1.64"
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[features]
|
||||
compat = []
|
||||
|
||||
[dependencies]
|
||||
once_cell = "1.13.0"
|
||||
proc-macro-crate = "1.0.0"
|
||||
|
@ -14,7 +14,8 @@ edition = "2021"
|
||||
all-features = true
|
||||
|
||||
[features]
|
||||
compat = []
|
||||
# Allow extra characters in signature IDs not allowed in the specification.
|
||||
compat-signature-id = []
|
||||
ring-compat = ["dep:subslice"]
|
||||
unstable-exhaustive-types = []
|
||||
|
||||
|
@ -85,9 +85,9 @@ fn split_id(id: &str) -> Result<(Algorithm, String), Error> {
|
||||
|
||||
let version = signature_id[1];
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
#[cfg(feature = "compat-signature-id")]
|
||||
const EXTRA_ALLOWED: [u8; 3] = [b'_', b'+', b'/'];
|
||||
#[cfg(not(feature = "compat"))]
|
||||
#[cfg(not(feature = "compat-signature-id"))]
|
||||
const EXTRA_ALLOWED: [u8; 1] = [b'_'];
|
||||
if !version.bytes().all(|ch| ch.is_ascii_alphanumeric() || EXTRA_ALLOWED.contains(&ch)) {
|
||||
return Err(Error::InvalidVersion(version.into()));
|
||||
|
@ -88,17 +88,43 @@ full = [
|
||||
"markdown",
|
||||
]
|
||||
|
||||
# Increase compatibility with other parts of the Matrix ecosystem, at the
|
||||
# expense of weird behaviour where things deviate from the specification.
|
||||
#
|
||||
# For example, some mandatory string fields are defaulted to an empty string if
|
||||
# missing with this feature.
|
||||
# Enable all compatibility hacks. Deprecated.
|
||||
compat = [
|
||||
"ruma-common/compat",
|
||||
"ruma-client-api?/compat",
|
||||
"ruma-federation-api?/compat",
|
||||
"ruma-signatures?/compat",
|
||||
"compat-key-id",
|
||||
"compat-user-id",
|
||||
"compat-empty-string-null",
|
||||
"compat-null",
|
||||
"compat-optional",
|
||||
"compat-unset-avatar",
|
||||
"compat-get-3pids",
|
||||
"compat-signature-id",
|
||||
]
|
||||
# Don't validate the version part in `KeyId`.
|
||||
compat-key-id = ["ruma-common/compat-key-id"]
|
||||
# Allow some user IDs that are invalid even with the specified historical
|
||||
# user ID scheme.
|
||||
compat-user-id = ["ruma-common/compat-user-id"]
|
||||
# Allow some mandatory fields in requests / responses to be missing, defaulting
|
||||
# them to an empty string in deserialization.
|
||||
compat-empty-string-null = [
|
||||
"ruma-common/compat-empty-string-null",
|
||||
"ruma-client-api?/compat-empty-string-null",
|
||||
"ruma-federation-api?/compat-empty-string-null",
|
||||
]
|
||||
# Allow certain fields to be `null` for compatibility, treating that the same as
|
||||
# the field being absent.
|
||||
compat-null = ["ruma-common/compat-null"]
|
||||
# Allow certain fields to be absent even though the spec marks them as
|
||||
# mandatory. Deserialization will yield a default value like an empty string.
|
||||
compat-optional = ["ruma-common/compat-optional"]
|
||||
# Unset avatars by sending an empty string, same as what Element Web does, c.f.
|
||||
# https://github.com/matrix-org/matrix-spec/issues/378#issuecomment-1055831264
|
||||
compat-unset-avatar = ["ruma-client-api?/compat-unset-avatar"]
|
||||
# Always serialize the threepids response field in `get_3pids::v3::Response`,
|
||||
# even if its value is an empty list.
|
||||
compat-get-3pids = ["ruma-client-api?/compat-get-3pids"]
|
||||
# Allow extra characters in signature IDs not allowed in the specification.
|
||||
compat-signature-id = ["ruma-signatures?/compat-signature-id"]
|
||||
|
||||
# Specific compatibility for past ring public/private key documents.
|
||||
ring-compat = ["dep:ruma-signatures", "ruma-signatures?/ring-compat"]
|
||||
|
@ -189,7 +189,12 @@ impl CiTask {
|
||||
|
||||
/// Check ruma-common with onjy the required features with the stable version.
|
||||
fn stable_common(&self) -> Result<()> {
|
||||
cmd!("rustup run stable cargo check -p ruma-common --no-default-features --features client,server").run().map_err(Into::into)
|
||||
cmd!(
|
||||
"rustup run stable cargo check -p ruma-common
|
||||
--no-default-features --features client,server"
|
||||
)
|
||||
.run()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Run tests on all crates with almost all features with the stable version.
|
||||
@ -204,7 +209,12 @@ impl CiTask {
|
||||
|
||||
/// Test ruma-common with the compat feature with the stable version.
|
||||
fn test_common(&self) -> Result<()> {
|
||||
cmd!("rustup run stable cargo test -p ruma-common --features events --features compat compat").run().map_err(Into::into)
|
||||
cmd!(
|
||||
"rustup run stable cargo test -p ruma-common
|
||||
--features events,compat-empty-string-null,compat-user-id compat"
|
||||
)
|
||||
.run()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Run all the tasks that use the nightly version.
|
||||
|
Loading…
x
Reference in New Issue
Block a user