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
|
||||
([Spec change removing the size limit][spec])
|
||||
* 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
|
||||
|
||||
|
@ -22,6 +22,7 @@ client = []
|
||||
server = []
|
||||
|
||||
api = ["http", "thiserror"]
|
||||
canonical-json = []
|
||||
compat = ["ruma-macros/compat", "ruma-identifiers-validation/compat"]
|
||||
events = ["thiserror"]
|
||||
js = ["js-sys", "getrandom?/js", "uuid?/js"]
|
||||
|
@ -1,16 +1,19 @@
|
||||
//! Canonical JSON types and related functions.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use serde::Serialize;
|
||||
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.
|
||||
#[cfg(feature = "canonical-json")]
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::exhaustive_enums)]
|
||||
pub enum Error {
|
||||
pub enum CanonicalJsonError {
|
||||
/// The numeric value failed conversion to js_int::Int.
|
||||
IntConvert,
|
||||
|
||||
@ -18,27 +21,31 @@ pub enum Error {
|
||||
SerDe(JsonError),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
impl fmt::Display for CanonicalJsonError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Error::IntConvert => f.write_str("number found is not a valid `js_int::Int`"),
|
||||
Error::SerDe(err) => write!(f, "serde Error: {err}"),
|
||||
CanonicalJsonError::IntConvert => {
|
||||
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`.
|
||||
pub fn try_from_json_map(
|
||||
json: serde_json::Map<String, JsonValue>,
|
||||
) -> Result<CanonicalJsonObject, Error> {
|
||||
) -> Result<CanonicalJsonObject, CanonicalJsonError> {
|
||||
json.into_iter().map(|(k, v)| Ok((k, v.try_into()?))).collect()
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
serde_json::to_value(value).map_err(Error::SerDe)?.try_into()
|
||||
pub fn to_canonical_value<T: Serialize>(
|
||||
value: T,
|
||||
) -> Result<value::CanonicalJsonValue, CanonicalJsonError> {
|
||||
serde_json::to_value(value).map_err(CanonicalJsonError::SerDe)?.try_into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
@ -4,12 +4,14 @@ use js_int::Int;
|
||||
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
|
||||
use serde_json::{to_string as to_json_string, Value as JsonValue};
|
||||
|
||||
use super::Error;
|
||||
use super::CanonicalJsonError;
|
||||
|
||||
/// 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.
|
||||
#[cfg(feature = "canonical-json")]
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
#[allow(clippy::exhaustive_enums)]
|
||||
pub enum CanonicalJsonValue {
|
||||
@ -67,7 +69,7 @@ pub enum CanonicalJsonValue {
|
||||
/// # use ruma_common::serde::CanonicalJsonValue;
|
||||
/// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
|
||||
/// ```
|
||||
Object(Object),
|
||||
Object(CanonicalJsonObject),
|
||||
}
|
||||
|
||||
impl CanonicalJsonValue {
|
||||
@ -104,7 +106,7 @@ impl CanonicalJsonValue {
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
Self::Object(o) => Some(o),
|
||||
_ => None,
|
||||
@ -120,7 +122,7 @@ impl CanonicalJsonValue {
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
Self::Object(o) => Some(o),
|
||||
_ => None,
|
||||
@ -195,14 +197,14 @@ impl fmt::Display for CanonicalJsonValue {
|
||||
}
|
||||
|
||||
impl TryFrom<JsonValue> for CanonicalJsonValue {
|
||||
type Error = Error;
|
||||
type Error = CanonicalJsonError;
|
||||
|
||||
fn try_from(val: JsonValue) -> Result<Self, Self::Error> {
|
||||
Ok(match val {
|
||||
JsonValue::Bool(b) => Self::Bool(b),
|
||||
JsonValue::Number(num) => Self::Integer(
|
||||
Int::try_from(num.as_i64().ok_or(Error::IntConvert)?)
|
||||
.map_err(|_| Error::IntConvert)?,
|
||||
Int::try_from(num.as_i64().ok_or(CanonicalJsonError::IntConvert)?)
|
||||
.map_err(|_| CanonicalJsonError::IntConvert)?,
|
||||
),
|
||||
JsonValue::Array(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(
|
||||
obj.into_iter()
|
||||
.map(|(k, v)| Ok((k, v.try_into()?)))
|
||||
.collect::<Result<Object, _>>()?,
|
||||
.collect::<Result<CanonicalJsonObject, _>>()?,
|
||||
),
|
||||
JsonValue::Null => Self::Null,
|
||||
})
|
||||
@ -267,7 +269,7 @@ variant_impls!(Bool(bool));
|
||||
variant_impls!(Integer(Int));
|
||||
variant_impls!(String(String));
|
||||
variant_impls!(Array(Vec<CanonicalJsonValue>));
|
||||
variant_impls!(Object(Object));
|
||||
variant_impls!(Object(CanonicalJsonObject));
|
||||
|
||||
impl Serialize for CanonicalJsonValue {
|
||||
#[inline]
|
@ -25,6 +25,8 @@ extern crate self as ruma_common;
|
||||
#[cfg(feature = "api")]
|
||||
pub mod api;
|
||||
pub mod authentication;
|
||||
#[cfg(feature = "canonical-json")]
|
||||
pub mod canonical_json;
|
||||
pub mod directory;
|
||||
pub mod encryption;
|
||||
#[cfg(feature = "events")]
|
||||
@ -42,8 +44,12 @@ pub mod to_device;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
pub use identifiers::*;
|
||||
pub use time::{MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch};
|
||||
#[cfg(feature = "canonical-json")]
|
||||
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
|
||||
// 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;
|
||||
mod buf;
|
||||
pub mod can_be_empty;
|
||||
mod canonical_json;
|
||||
mod cow;
|
||||
pub mod duration;
|
||||
mod empty;
|
||||
@ -26,11 +25,6 @@ pub use self::{
|
||||
base64::{Base64, Base64DecodeError},
|
||||
buf::{json_to_buf, slice_to_buf},
|
||||
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,
|
||||
empty::vec_as_map_of_empty,
|
||||
raw::Raw,
|
||||
|
@ -25,7 +25,7 @@ ed25519-dalek = "1.0.1"
|
||||
pkcs8 = { version = "0.9.0", features = ["alloc"] }
|
||||
# because dalek uses an older version of rand_core
|
||||
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"
|
||||
sha2 = "0.9.5"
|
||||
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 ruma_common::{
|
||||
serde::{base64::Standard, Base64, CanonicalJsonObject, CanonicalJsonValue},
|
||||
OwnedEventId, OwnedServerName, RoomVersionId, UserId,
|
||||
serde::{base64::Standard, Base64},
|
||||
CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedServerName, RoomVersionId, UserId,
|
||||
};
|
||||
use serde_json::{from_str as from_json_str, to_string as to_json_string};
|
||||
use sha2::{digest::Digest, Sha256};
|
||||
@ -881,8 +881,7 @@ mod tests {
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use ruma_common::{
|
||||
serde::{Base64, CanonicalJsonValue},
|
||||
RoomVersionId, ServerSigningKeyId, SigningKeyAlgorithm,
|
||||
serde::Base64, CanonicalJsonValue, RoomVersionId, ServerSigningKeyId, SigningKeyAlgorithm,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
|
@ -52,7 +52,7 @@ pub use functions::{
|
||||
redact_in_place, reference_hash, sign_json, verify_event, verify_json,
|
||||
};
|
||||
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 verification::Verified;
|
||||
|
||||
|
@ -17,6 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[features]
|
||||
api = ["ruma-common/api"]
|
||||
canonical-json = ["ruma-common/canonical-json"]
|
||||
client = ["ruma-client"]
|
||||
events = ["ruma-common/events"]
|
||||
signatures = ["ruma-signatures"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user