blob: bfe1fc5df32f57598d080ae97d9584646f8e158e [file] [log] [blame]
//! Contains structures and functions to aid in various TUF data interchange formats.
mod cjson;
use json;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use std::fmt::Debug;
use std::io::{Read, Write};
use Result;
use error::Error;
/// The format used for data interchange, serialization, and deserialization.
pub trait DataInterchange: Debug {
/// The type of data that is contained in the `signed` portion of metadata.
type RawData: Serialize + DeserializeOwned;
/// The data interchange's extension.
fn extension() -> &'static str;
/// A function that canonicalizes data to allow for deterministic signatures.
fn canonicalize(raw_data: &Self::RawData) -> Result<Vec<u8>>;
/// Deserialize from `RawData`.
fn deserialize<T>(raw_data: &Self::RawData) -> Result<T>
where
T: DeserializeOwned;
/// Serialize into `RawData`.
fn serialize<T>(data: &T) -> Result<Self::RawData>
where
T: Serialize;
/// Write a struct to a stream.
fn to_writer<W, T: ?Sized>(writer: W, value: &T) -> Result<()>
where
W: Write,
T: Serialize;
/// Read a struct from a stream.
fn from_reader<R, T>(rdr: R) -> Result<T>
where
R: Read,
T: DeserializeOwned;
}
/// JSON data interchange.
#[derive(Debug)]
pub struct JsonDataInterchange {}
impl DataInterchange for JsonDataInterchange {
type RawData = json::Value;
/// ```
/// use tuf::interchange::{DataInterchange, JsonDataInterchange};
///
/// assert_eq!(JsonDataInterchange::extension(), "json");
/// ```
fn extension() -> &'static str {
"json"
}
/// ```
/// use tuf::interchange::{DataInterchange, JsonDataInterchange};
/// use std::collections::HashMap;
///
/// let jsn: &[u8] = br#"{"foo": "bar", "baz": "quux"}"#;
/// let raw = JsonDataInterchange::from_reader(jsn).unwrap();
/// let out = JsonDataInterchange::canonicalize(&raw).unwrap();
/// assert_eq!(out, br#"{"baz":"quux","foo":"bar"}"#);
/// ```
fn canonicalize(raw_data: &Self::RawData) -> Result<Vec<u8>> {
cjson::canonicalize(raw_data).map_err(|e| Error::Opaque(e))
}
/// ```
/// use tuf::interchange::{DataInterchange, JsonDataInterchange};
/// use std::collections::HashMap;
///
/// let jsn: &[u8] = br#"{"foo": "bar", "baz": "quux"}"#;
/// let raw = JsonDataInterchange::from_reader(jsn).unwrap();
/// let mut map = HashMap::new();
/// let _ = map.insert("foo".to_string(), "bar".to_string());
/// let _ = map.insert("baz".to_string(), "quux".to_string());
/// let de: HashMap<String, String> = JsonDataInterchange::deserialize(&raw).unwrap();
/// assert_eq!(de, map);
/// ```
fn deserialize<T>(raw_data: &Self::RawData) -> Result<T>
where
T: DeserializeOwned,
{
Ok(json::from_value(raw_data.clone())?)
}
/// ```
/// use tuf::interchange::{DataInterchange, JsonDataInterchange};
/// use std::collections::HashMap;
///
/// let arr = vec![1, 2, 3];
/// let raw = JsonDataInterchange::serialize(&arr).unwrap();
/// assert!(raw.is_array());
///
/// let mut map = HashMap::new();
/// let _ = map.insert("abc", 123);
/// let raw = JsonDataInterchange::serialize(&map).unwrap();
/// assert!(raw.is_object());
/// ```
fn serialize<T>(data: &T) -> Result<Self::RawData>
where
T: Serialize,
{
Ok(json::to_value(data)?)
}
/// ```
/// use tuf::interchange::{DataInterchange, JsonDataInterchange};
///
/// let arr = vec![1, 2, 3];
/// let mut buf = Vec::new();
/// JsonDataInterchange::to_writer(&mut buf, &arr).unwrap();
/// assert!(&buf == b"[1, 2, 3]" || &buf == b"[1,2,3]");
/// ```
fn to_writer<W, T: ?Sized>(writer: W, value: &T) -> Result<()>
where
W: Write,
T: Serialize,
{
Ok(json::to_writer(writer, value)?)
}
/// ```
/// use tuf::interchange::{DataInterchange, JsonDataInterchange};
/// use std::collections::HashMap;
///
/// let jsn: &[u8] = br#"{"foo": "bar", "baz": "quux"}"#;
/// let _: HashMap<String, String> = JsonDataInterchange::from_reader(jsn).unwrap();
/// ```
fn from_reader<R, T>(rdr: R) -> Result<T>
where
R: Read,
T: DeserializeOwned,
{
Ok(json::from_reader(rdr)?)
}
}