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_json::Error as JsonError;
|
||||
use serde_json::{Error as JsonError, Map as JsonObject, Value as JsonValue};
|
||||
|
||||
pub mod value;
|
||||
|
||||
use value::Object as CanonicalJsonObject;
|
||||
|
||||
/// 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
|
||||
@ -45,12 +47,29 @@ impl fmt::Display 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)]
|
||||
mod test {
|
||||
use std::convert::TryInto;
|
||||
use std::{collections::BTreeMap, convert::TryInto};
|
||||
|
||||
use super::{to_string as to_canonical_json_string, value::CanonicalJsonValue};
|
||||
use serde_json::{from_str as from_json_str, json, to_string as to_json_string};
|
||||
use super::{
|
||||
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]
|
||||
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}}"#
|
||||
)
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
/// The inner type of `CanonicalJsonValue::Object`.
|
||||
pub type Object = BTreeMap<String, CanonicalJsonValue>;
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub enum CanonicalJsonValue {
|
||||
/// Represents a JSON null value.
|
||||
@ -72,7 +75,7 @@ pub enum CanonicalJsonValue {
|
||||
/// # use ruma_serde::CanonicalJsonValue;
|
||||
/// let v: CanonicalJsonValue = json!({ "an": "object" }).try_into().unwrap();
|
||||
/// ```
|
||||
Object(BTreeMap<String, CanonicalJsonValue>),
|
||||
Object(Object),
|
||||
}
|
||||
|
||||
impl Default for CanonicalJsonValue {
|
||||
@ -133,7 +136,7 @@ impl TryFrom<JsonValue> for CanonicalJsonValue {
|
||||
JsonValue::Object(obj) => Self::Object(
|
||||
obj.into_iter()
|
||||
.map(|(k, v)| Ok((k, v.try_into()?)))
|
||||
.collect::<Result<BTreeMap<_, _>, _>>()?,
|
||||
.collect::<Result<Object, _>>()?,
|
||||
),
|
||||
JsonValue::Null => Self::Null,
|
||||
})
|
||||
|
@ -15,7 +15,9 @@ pub mod urlencoded;
|
||||
|
||||
pub use can_be_empty::{is_empty, CanBeEmpty};
|
||||
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 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 ring::digest::{digest, SHA256};
|
||||
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 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.
|
||||
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`.
|
||||
///
|
||||
/// If `signatures` is already present, the new signature will be appended to the existing ones.
|
||||
|
@ -51,7 +51,7 @@ use std::{
|
||||
|
||||
pub use functions::{
|
||||
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 signatures::Signature;
|
||||
|
Loading…
x
Reference in New Issue
Block a user