common: Move CanonicalJson out of serde mod and behind a Cargo feature
This commit is contained in:
parent
e96b197d4d
commit
402b2764fb
@ -17,6 +17,8 @@ Breaking changes:
|
|||||||
* Room name size limits were never enforced by servers
|
* Room name size limits were never enforced by servers
|
||||||
([Spec change removing the size limit][spec])
|
([Spec change removing the size limit][spec])
|
||||||
* Remove `RoomMessageFeedbackEvent` and associated types and variants according to MSC3582
|
* Remove `RoomMessageFeedbackEvent` and associated types and variants according to MSC3582
|
||||||
|
* Move `CanonicalJson`, `CanonicalJsonObject` and `CanonicalJsonError` out of
|
||||||
|
the `serde` module and behind the cargo feature flag `canonical-json`
|
||||||
|
|
||||||
[spec]: https://github.com/matrix-org/matrix-spec-proposals/pull/3669
|
[spec]: https://github.com/matrix-org/matrix-spec-proposals/pull/3669
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ client = []
|
|||||||
server = []
|
server = []
|
||||||
|
|
||||||
api = ["http", "thiserror"]
|
api = ["http", "thiserror"]
|
||||||
|
canonical-json = []
|
||||||
compat = ["ruma-macros/compat", "ruma-identifiers-validation/compat"]
|
compat = ["ruma-macros/compat", "ruma-identifiers-validation/compat"]
|
||||||
events = ["thiserror"]
|
events = ["thiserror"]
|
||||||
js = ["js-sys", "getrandom?/js", "uuid?/js"]
|
js = ["js-sys", "getrandom?/js", "uuid?/js"]
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
|
//! Canonical JSON types and related functions.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{Error as JsonError, Value as JsonValue};
|
use serde_json::{Error as JsonError, Value as JsonValue};
|
||||||
|
|
||||||
pub mod value;
|
mod value;
|
||||||
|
|
||||||
use value::Object as CanonicalJsonObject;
|
pub use self::value::{CanonicalJsonObject, CanonicalJsonValue};
|
||||||
|
|
||||||
/// The set of possible errors when serializing to canonical JSON.
|
/// The set of possible errors when serializing to canonical JSON.
|
||||||
|
#[cfg(feature = "canonical-json")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(clippy::exhaustive_enums)]
|
#[allow(clippy::exhaustive_enums)]
|
||||||
pub enum Error {
|
pub enum CanonicalJsonError {
|
||||||
/// The numeric value failed conversion to js_int::Int.
|
/// The numeric value failed conversion to js_int::Int.
|
||||||
IntConvert,
|
IntConvert,
|
||||||
|
|
||||||
@ -18,27 +21,31 @@ pub enum Error {
|
|||||||
SerDe(JsonError),
|
SerDe(JsonError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for CanonicalJsonError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Error::IntConvert => f.write_str("number found is not a valid `js_int::Int`"),
|
CanonicalJsonError::IntConvert => {
|
||||||
Error::SerDe(err) => write!(f, "serde Error: {err}"),
|
f.write_str("number found is not a valid `js_int::Int`")
|
||||||
|
}
|
||||||
|
CanonicalJsonError::SerDe(err) => write!(f, "serde Error: {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for Error {}
|
impl std::error::Error for CanonicalJsonError {}
|
||||||
|
|
||||||
/// Fallible conversion from a `serde_json::Map` to a `CanonicalJsonObject`.
|
/// Fallible conversion from a `serde_json::Map` to a `CanonicalJsonObject`.
|
||||||
pub fn try_from_json_map(
|
pub fn try_from_json_map(
|
||||||
json: serde_json::Map<String, JsonValue>,
|
json: serde_json::Map<String, JsonValue>,
|
||||||
) -> Result<CanonicalJsonObject, Error> {
|
) -> Result<CanonicalJsonObject, CanonicalJsonError> {
|
||||||
json.into_iter().map(|(k, v)| Ok((k, v.try_into()?))).collect()
|
json.into_iter().map(|(k, v)| Ok((k, v.try_into()?))).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fallible conversion from any value that impl's `Serialize` to a `CanonicalJsonValue`.
|
/// Fallible conversion from any value that impl's `Serialize` to a `CanonicalJsonValue`.
|
||||||
pub fn to_canonical_value<T: Serialize>(value: T) -> Result<value::CanonicalJsonValue, Error> {
|
pub fn to_canonical_value<T: Serialize>(
|
||||||
serde_json::to_value(value).map_err(Error::SerDe)?.try_into()
|
value: T,
|
||||||
|
) -> Result<value::CanonicalJsonValue, CanonicalJsonError> {
|
||||||
|
serde_json::to_value(value).map_err(CanonicalJsonError::SerDe)?.try_into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
@ -4,12 +4,14 @@ use js_int::Int;
|
|||||||
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
|
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
|
||||||
use serde_json::{to_string as to_json_string, Value as JsonValue};
|
use serde_json::{to_string as to_json_string, Value as JsonValue};
|
||||||
|
|
||||||
use super::Error;
|
use super::CanonicalJsonError;
|
||||||
|
|
||||||
/// The inner type of `CanonicalJsonValue::Object`.
|
/// The inner type of `CanonicalJsonValue::Object`.
|
||||||
pub type Object = BTreeMap<String, CanonicalJsonValue>;
|
#[cfg(feature = "canonical-json")]
|
||||||
|
pub type CanonicalJsonObject = BTreeMap<String, CanonicalJsonValue>;
|
||||||
|
|
||||||
/// Represents a canonical JSON value as per the Matrix specification.
|
/// Represents a canonical JSON value as per the Matrix specification.
|
||||||
|
#[cfg(feature = "canonical-json")]
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
#[allow(clippy::exhaustive_enums)]
|
#[allow(clippy::exhaustive_enums)]
|
||||||
pub enum CanonicalJsonValue {
|
pub enum CanonicalJsonValue {
|
||||||
@ -67,7 +69,7 @@ pub enum CanonicalJsonValue {
|
|||||||
/// # use ruma_common::serde::CanonicalJsonValue;
|
/// # use ruma_common::serde::CanonicalJsonValue;
|
||||||
/// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
|
/// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
Object(Object),
|
Object(CanonicalJsonObject),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanonicalJsonValue {
|
impl CanonicalJsonValue {
|
||||||
@ -104,7 +106,7 @@ impl CanonicalJsonValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If the `CanonicalJsonValue` is an `Object`, return a reference to the inner value.
|
/// If the `CanonicalJsonValue` is an `Object`, return a reference to the inner value.
|
||||||
pub fn as_object(&self) -> Option<&Object> {
|
pub fn as_object(&self) -> Option<&CanonicalJsonObject> {
|
||||||
match self {
|
match self {
|
||||||
Self::Object(o) => Some(o),
|
Self::Object(o) => Some(o),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -120,7 +122,7 @@ impl CanonicalJsonValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If the `CanonicalJsonValue` is an `Object`, return a mutable reference to the inner value.
|
/// If the `CanonicalJsonValue` is an `Object`, return a mutable reference to the inner value.
|
||||||
pub fn as_object_mut(&mut self) -> Option<&mut Object> {
|
pub fn as_object_mut(&mut self) -> Option<&mut CanonicalJsonObject> {
|
||||||
match self {
|
match self {
|
||||||
Self::Object(o) => Some(o),
|
Self::Object(o) => Some(o),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -195,14 +197,14 @@ impl fmt::Display for CanonicalJsonValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<JsonValue> for CanonicalJsonValue {
|
impl TryFrom<JsonValue> for CanonicalJsonValue {
|
||||||
type Error = Error;
|
type Error = CanonicalJsonError;
|
||||||
|
|
||||||
fn try_from(val: JsonValue) -> Result<Self, Self::Error> {
|
fn try_from(val: JsonValue) -> Result<Self, Self::Error> {
|
||||||
Ok(match val {
|
Ok(match val {
|
||||||
JsonValue::Bool(b) => Self::Bool(b),
|
JsonValue::Bool(b) => Self::Bool(b),
|
||||||
JsonValue::Number(num) => Self::Integer(
|
JsonValue::Number(num) => Self::Integer(
|
||||||
Int::try_from(num.as_i64().ok_or(Error::IntConvert)?)
|
Int::try_from(num.as_i64().ok_or(CanonicalJsonError::IntConvert)?)
|
||||||
.map_err(|_| Error::IntConvert)?,
|
.map_err(|_| CanonicalJsonError::IntConvert)?,
|
||||||
),
|
),
|
||||||
JsonValue::Array(vec) => {
|
JsonValue::Array(vec) => {
|
||||||
Self::Array(vec.into_iter().map(TryInto::try_into).collect::<Result<Vec<_>, _>>()?)
|
Self::Array(vec.into_iter().map(TryInto::try_into).collect::<Result<Vec<_>, _>>()?)
|
||||||
@ -211,7 +213,7 @@ impl TryFrom<JsonValue> for CanonicalJsonValue {
|
|||||||
JsonValue::Object(obj) => Self::Object(
|
JsonValue::Object(obj) => Self::Object(
|
||||||
obj.into_iter()
|
obj.into_iter()
|
||||||
.map(|(k, v)| Ok((k, v.try_into()?)))
|
.map(|(k, v)| Ok((k, v.try_into()?)))
|
||||||
.collect::<Result<Object, _>>()?,
|
.collect::<Result<CanonicalJsonObject, _>>()?,
|
||||||
),
|
),
|
||||||
JsonValue::Null => Self::Null,
|
JsonValue::Null => Self::Null,
|
||||||
})
|
})
|
||||||
@ -267,7 +269,7 @@ variant_impls!(Bool(bool));
|
|||||||
variant_impls!(Integer(Int));
|
variant_impls!(Integer(Int));
|
||||||
variant_impls!(String(String));
|
variant_impls!(String(String));
|
||||||
variant_impls!(Array(Vec<CanonicalJsonValue>));
|
variant_impls!(Array(Vec<CanonicalJsonValue>));
|
||||||
variant_impls!(Object(Object));
|
variant_impls!(Object(CanonicalJsonObject));
|
||||||
|
|
||||||
impl Serialize for CanonicalJsonValue {
|
impl Serialize for CanonicalJsonValue {
|
||||||
#[inline]
|
#[inline]
|
@ -25,6 +25,8 @@ extern crate self as ruma_common;
|
|||||||
#[cfg(feature = "api")]
|
#[cfg(feature = "api")]
|
||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod authentication;
|
pub mod authentication;
|
||||||
|
#[cfg(feature = "canonical-json")]
|
||||||
|
pub mod canonical_json;
|
||||||
pub mod directory;
|
pub mod directory;
|
||||||
pub mod encryption;
|
pub mod encryption;
|
||||||
#[cfg(feature = "events")]
|
#[cfg(feature = "events")]
|
||||||
@ -42,8 +44,12 @@ pub mod to_device;
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub use identifiers::*;
|
#[cfg(feature = "canonical-json")]
|
||||||
pub use time::{MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch};
|
pub use self::canonical_json::{CanonicalJsonError, CanonicalJsonObject, CanonicalJsonValue};
|
||||||
|
pub use self::{
|
||||||
|
identifiers::*,
|
||||||
|
time::{MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch},
|
||||||
|
};
|
||||||
|
|
||||||
// Wrapper around `Box<str>` that cannot be used in a meaningful way outside of
|
// 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
|
// this crate. Used for string enums because their `_Custom` variant can't be
|
||||||
|
@ -11,7 +11,6 @@ use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
|
|||||||
pub mod base64;
|
pub mod base64;
|
||||||
mod buf;
|
mod buf;
|
||||||
pub mod can_be_empty;
|
pub mod can_be_empty;
|
||||||
mod canonical_json;
|
|
||||||
mod cow;
|
mod cow;
|
||||||
pub mod duration;
|
pub mod duration;
|
||||||
mod empty;
|
mod empty;
|
||||||
@ -26,11 +25,6 @@ pub use self::{
|
|||||||
base64::{Base64, Base64DecodeError},
|
base64::{Base64, Base64DecodeError},
|
||||||
buf::{json_to_buf, slice_to_buf},
|
buf::{json_to_buf, slice_to_buf},
|
||||||
can_be_empty::{is_empty, CanBeEmpty},
|
can_be_empty::{is_empty, CanBeEmpty},
|
||||||
canonical_json::{
|
|
||||||
to_canonical_value, try_from_json_map,
|
|
||||||
value::{CanonicalJsonValue, Object as CanonicalJsonObject},
|
|
||||||
Error as CanonicalJsonError,
|
|
||||||
},
|
|
||||||
cow::deserialize_cow_str,
|
cow::deserialize_cow_str,
|
||||||
empty::vec_as_map_of_empty,
|
empty::vec_as_map_of_empty,
|
||||||
raw::Raw,
|
raw::Raw,
|
||||||
|
@ -25,7 +25,7 @@ ed25519-dalek = "1.0.1"
|
|||||||
pkcs8 = { version = "0.9.0", features = ["alloc"] }
|
pkcs8 = { version = "0.9.0", features = ["alloc"] }
|
||||||
# because dalek uses an older version of rand_core
|
# because dalek uses an older version of rand_core
|
||||||
rand = { version = "0.7", features = ["getrandom"] }
|
rand = { version = "0.7", features = ["getrandom"] }
|
||||||
ruma-common = { version = "0.9.2", path = "../ruma-common" }
|
ruma-common = { version = "0.9.2", path = "../ruma-common", features = ["canonical-json"] }
|
||||||
serde_json = "1.0.60"
|
serde_json = "1.0.60"
|
||||||
sha2 = "0.9.5"
|
sha2 = "0.9.5"
|
||||||
subslice = { version = "0.2.3", optional = true }
|
subslice = { version = "0.2.3", optional = true }
|
||||||
|
@ -8,8 +8,8 @@ use std::{
|
|||||||
|
|
||||||
use base64::{encode_config, STANDARD_NO_PAD, URL_SAFE_NO_PAD};
|
use base64::{encode_config, STANDARD_NO_PAD, URL_SAFE_NO_PAD};
|
||||||
use ruma_common::{
|
use ruma_common::{
|
||||||
serde::{base64::Standard, Base64, CanonicalJsonObject, CanonicalJsonValue},
|
serde::{base64::Standard, Base64},
|
||||||
OwnedEventId, OwnedServerName, RoomVersionId, UserId,
|
CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedServerName, RoomVersionId, UserId,
|
||||||
};
|
};
|
||||||
use serde_json::{from_str as from_json_str, to_string as to_json_string};
|
use serde_json::{from_str as from_json_str, to_string as to_json_string};
|
||||||
use sha2::{digest::Digest, Sha256};
|
use sha2::{digest::Digest, Sha256};
|
||||||
@ -881,8 +881,7 @@ mod tests {
|
|||||||
|
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use ruma_common::{
|
use ruma_common::{
|
||||||
serde::{Base64, CanonicalJsonValue},
|
serde::Base64, CanonicalJsonValue, RoomVersionId, ServerSigningKeyId, SigningKeyAlgorithm,
|
||||||
RoomVersionId, ServerSigningKeyId, SigningKeyAlgorithm,
|
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ pub use functions::{
|
|||||||
redact_in_place, reference_hash, sign_json, verify_event, verify_json,
|
redact_in_place, reference_hash, sign_json, verify_event, verify_json,
|
||||||
};
|
};
|
||||||
pub use keys::{Ed25519KeyPair, KeyPair, PublicKeyMap, PublicKeySet};
|
pub use keys::{Ed25519KeyPair, KeyPair, PublicKeyMap, PublicKeySet};
|
||||||
pub use ruma_common::serde::{CanonicalJsonError, CanonicalJsonObject, CanonicalJsonValue};
|
pub use ruma_common::{CanonicalJsonError, CanonicalJsonObject, CanonicalJsonValue};
|
||||||
pub use signatures::Signature;
|
pub use signatures::Signature;
|
||||||
pub use verification::Verified;
|
pub use verification::Verified;
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
api = ["ruma-common/api"]
|
api = ["ruma-common/api"]
|
||||||
|
canonical-json = ["ruma-common/canonical-json"]
|
||||||
client = ["ruma-client"]
|
client = ["ruma-client"]
|
||||||
events = ["ruma-common/events"]
|
events = ["ruma-common/events"]
|
||||||
signatures = ["ruma-signatures"]
|
signatures = ["ruma-signatures"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user