Add helper methods for CanonicalJsonObject construction
This commit is contained in:
parent
c04a9e71c5
commit
bc43e94d7e
@ -1,10 +1,12 @@
|
|||||||
use std::fmt;
|
use std::{convert::TryInto, fmt};
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Error as JsonError;
|
use serde_json::{Error as JsonError, Map as JsonObject, Value as JsonValue};
|
||||||
|
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
|
use value::Object as CanonicalJsonObject;
|
||||||
|
|
||||||
/// Returns a canonical JSON string according to Matrix specification.
|
/// Returns a canonical JSON string according to Matrix specification.
|
||||||
///
|
///
|
||||||
/// This function should be preferred over `serde_json::to_string` since it checks the size of the
|
/// This function should be preferred over `serde_json::to_string` since it checks the size of the
|
||||||
@ -45,12 +47,29 @@ impl fmt::Display for Error {
|
|||||||
|
|
||||||
impl std::error::Error for Error {}
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
|
/// Fallible conversion from a `serde_json::Map` to a `CanonicalJsonObject`.
|
||||||
|
pub fn try_from_json_map(
|
||||||
|
json: JsonObject<String, JsonValue>,
|
||||||
|
) -> Result<CanonicalJsonObject, Error> {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::convert::TryInto;
|
use std::{collections::BTreeMap, convert::TryInto};
|
||||||
|
|
||||||
use super::{to_string as to_canonical_json_string, value::CanonicalJsonValue};
|
use super::{
|
||||||
use serde_json::{from_str as from_json_str, json, to_string as to_json_string};
|
to_canonical_value, to_string as to_canonical_json_string, try_from_json_map,
|
||||||
|
value::CanonicalJsonValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
use js_int::int;
|
||||||
|
use serde_json::{from_str as from_json_str, json, to_string as to_json_string, Map};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_canon() {
|
fn serialize_canon() {
|
||||||
@ -97,4 +116,47 @@ mod test {
|
|||||||
r#"{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}"#
|
r#"{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}"#
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_map_to_canonical() {
|
||||||
|
let mut expected = BTreeMap::new();
|
||||||
|
expected.insert("foo".into(), CanonicalJsonValue::String("string".into()));
|
||||||
|
expected.insert(
|
||||||
|
"bar".into(),
|
||||||
|
CanonicalJsonValue::Array(vec![
|
||||||
|
CanonicalJsonValue::Integer(int!(0)),
|
||||||
|
CanonicalJsonValue::Integer(int!(1)),
|
||||||
|
CanonicalJsonValue::Integer(int!(2)),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut map = Map::new();
|
||||||
|
map.insert("foo".into(), json!("string"));
|
||||||
|
map.insert("bar".into(), json!(vec![0, 1, 2,]));
|
||||||
|
|
||||||
|
assert_eq!(try_from_json_map(map).unwrap(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn to_canonical() {
|
||||||
|
#[derive(Debug, serde::Serialize)]
|
||||||
|
struct Thing {
|
||||||
|
foo: String,
|
||||||
|
bar: Vec<u8>,
|
||||||
|
}
|
||||||
|
let t = Thing { foo: "string".into(), bar: vec![0, 1, 2] };
|
||||||
|
|
||||||
|
let mut expected = BTreeMap::new();
|
||||||
|
expected.insert("foo".into(), CanonicalJsonValue::String("string".into()));
|
||||||
|
expected.insert(
|
||||||
|
"bar".into(),
|
||||||
|
CanonicalJsonValue::Array(vec![
|
||||||
|
CanonicalJsonValue::Integer(int!(0)),
|
||||||
|
CanonicalJsonValue::Integer(int!(1)),
|
||||||
|
CanonicalJsonValue::Integer(int!(2)),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(to_canonical_value(t).unwrap(), CanonicalJsonValue::Object(expected));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,9 @@ use serde_json::{to_string as to_json_string, Value as JsonValue};
|
|||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
|
||||||
|
/// The inner type of `CanonicalJsonValue::Object`.
|
||||||
|
pub type Object = BTreeMap<String, CanonicalJsonValue>;
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub enum CanonicalJsonValue {
|
pub enum CanonicalJsonValue {
|
||||||
/// Represents a JSON null value.
|
/// Represents a JSON null value.
|
||||||
@ -72,7 +75,7 @@ pub enum CanonicalJsonValue {
|
|||||||
/// # use ruma_serde::CanonicalJsonValue;
|
/// # use ruma_serde::CanonicalJsonValue;
|
||||||
/// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
|
/// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
Object(BTreeMap<String, CanonicalJsonValue>),
|
Object(Object),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CanonicalJsonValue {
|
impl Default for CanonicalJsonValue {
|
||||||
@ -133,7 +136,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<BTreeMap<_, _>, _>>()?,
|
.collect::<Result<Object, _>>()?,
|
||||||
),
|
),
|
||||||
JsonValue::Null => Self::Null,
|
JsonValue::Null => Self::Null,
|
||||||
})
|
})
|
||||||
|
@ -15,7 +15,9 @@ pub mod urlencoded;
|
|||||||
|
|
||||||
pub use can_be_empty::{is_empty, CanBeEmpty};
|
pub use can_be_empty::{is_empty, CanBeEmpty};
|
||||||
pub use canonical_json::{
|
pub use canonical_json::{
|
||||||
to_string as to_canonical_json_string, value::CanonicalJsonValue, Error as CanonicalJsonError,
|
to_canonical_value, to_string as to_canonical_json_string, try_from_json_map,
|
||||||
|
value::{CanonicalJsonValue, Object as CanonicalJsonObject},
|
||||||
|
Error as CanonicalJsonError,
|
||||||
};
|
};
|
||||||
pub use cow::deserialize_cow_str;
|
pub use cow::deserialize_cow_str;
|
||||||
pub use empty::vec_as_map_of_empty;
|
pub use empty::vec_as_map_of_empty;
|
||||||
|
@ -5,7 +5,7 @@ use std::{collections::BTreeMap, mem};
|
|||||||
use base64::{decode_config, encode_config, STANDARD_NO_PAD, URL_SAFE_NO_PAD};
|
use base64::{decode_config, encode_config, STANDARD_NO_PAD, URL_SAFE_NO_PAD};
|
||||||
use ring::digest::{digest, SHA256};
|
use ring::digest::{digest, SHA256};
|
||||||
use ruma_identifiers::RoomVersionId;
|
use ruma_identifiers::RoomVersionId;
|
||||||
use ruma_serde::{to_canonical_json_string, CanonicalJsonValue};
|
use ruma_serde::{to_canonical_json_string, CanonicalJsonObject, CanonicalJsonValue};
|
||||||
use serde_json::from_str as from_json_str;
|
use serde_json::from_str as from_json_str;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -73,9 +73,6 @@ static CONTENT_HASH_FIELDS_TO_REMOVE: &[&str] = &["hashes", "signatures", "unsig
|
|||||||
/// The fields to remove from a JSON object when creating a reference hash of an event.
|
/// The fields to remove from a JSON object when creating a reference hash of an event.
|
||||||
static REFERENCE_HASH_FIELDS_TO_REMOVE: &[&str] = &["age_ts", "signatures", "unsigned"];
|
static REFERENCE_HASH_FIELDS_TO_REMOVE: &[&str] = &["age_ts", "signatures", "unsigned"];
|
||||||
|
|
||||||
/// The inner type of `CanonicalJsonValue::Object`.
|
|
||||||
pub type CanonicalJsonObject = BTreeMap<String, CanonicalJsonValue>;
|
|
||||||
|
|
||||||
/// Signs an arbitrary JSON object and adds the signature to an object under the key `signatures`.
|
/// Signs an arbitrary JSON object and adds the signature to an object under the key `signatures`.
|
||||||
///
|
///
|
||||||
/// If `signatures` is already present, the new signature will be appended to the existing ones.
|
/// If `signatures` is already present, the new signature will be appended to the existing ones.
|
||||||
|
@ -51,7 +51,7 @@ use std::{
|
|||||||
|
|
||||||
pub use functions::{
|
pub use functions::{
|
||||||
canonical_json, content_hash, hash_and_sign_event, redact, reference_hash, sign_json,
|
canonical_json, content_hash, hash_and_sign_event, redact, reference_hash, sign_json,
|
||||||
verify_event, verify_json, CanonicalJsonObject,
|
verify_event, verify_json,
|
||||||
};
|
};
|
||||||
pub use keys::{Ed25519KeyPair, KeyPair, PublicKeyMap, PublicKeySet};
|
pub use keys::{Ed25519KeyPair, KeyPair, PublicKeyMap, PublicKeySet};
|
||||||
pub use signatures::Signature;
|
pub use signatures::Signature;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user