rust_multicodec/lib.rs
1//! This library is a Rust implementation of the https://github.com/multiformats/multicodec project.
2//!
3//! This crate also can be used to encode and decode an object.
4//! Currently only JSON is supported
5
6extern crate integer_encoding;
7extern crate serde;
8extern crate serde_json;
9#[macro_use]
10extern crate serde_derive;
11
12use std::str;
13use serde::Serialize;
14use serde::de::DeserializeOwned;
15
16pub mod codec_prefix;
17pub mod codec;
18
19pub struct DecodeResult<T> {
20 pub data: T,
21 pub codec: codec::CodecType
22}
23
24/// Returns the encoded object with a prefix of the given codec.
25/// Note that the object must implement Serialize trait from serde's lib
26///
27/// # Arguments
28///
29/// * `codec` - The codec type, eg. CodecType::JSON
30/// * `object` - the object reference to be encoded
31///
32/// # Example
33///
34/// ```
35/// extern crate rust_multicodec;
36/// #[macro_use]
37/// extern crate serde_derive;
38/// #[derive(Serialize)]
39/// #[derive(Debug)]
40/// struct Person {
41/// name: String
42/// }
43///
44/// fn main(){
45/// let to_be_encoded=Person{name:String::from("sanyi")};
46/// println!("{:?}",rust_multicodec::encode(rust_multicodec::codec::CodecType::JSON, &to_be_encoded));
47/// // it will print: Ok([129, 30, 123, 34, 110, 97, 109, 101, 34, 58, 34, 115, 97, 110, 121, 105, 34, 125])
48/// }
49/// ```
50///
51pub fn encode<T: Serialize>(codec: codec::CodecType, object: &T) -> Result<Vec<u8>, String> {
52 match codec {
53 codec::CodecType::JSON => {
54 match serde_json::to_string(&object){
55 Ok(json) => codec_prefix::add(codec, json.as_bytes()).map_err(|io_error| -> String {
56 format!("Could not add prefix to the given object. Error: {:?}", io_error.kind())
57 }),
58 Err(err) => Err(format!("Could not serialize the given object. Serde error: {:?}", err))
59 }
60 }
61 }
62}
63
64/// Decodes a byte array back into an Object.
65/// Note that the object must implement Deserialize trait from serde's lib
66///
67/// # Arguments
68///
69/// * `encoded_data` - The data that was encoded with the encode method
70///
71/// # Example
72///
73/// ```
74/// extern crate rust_multicodec;
75/// #[macro_use]
76/// extern crate serde_derive;
77/// #[derive(Serialize, Deserialize)]
78/// #[derive(Debug)]
79/// struct Person {
80/// name: String
81/// }
82///
83/// fn main(){
84/// let to_be_encoded=Person{name:String::from("sanyi")};
85/// let encoded=rust_multicodec::encode(rust_multicodec::codec::CodecType::JSON, &to_be_encoded).unwrap();
86/// let decoded:Person=rust_multicodec::decode(encoded.as_ref()).unwrap().data;
87/// println!("{:?}",decoded);
88/// // it will print: Person { name: "sanyi" }
89/// }
90/// ```
91///
92pub fn decode<T: DeserializeOwned>(encoded_data: &[u8]) -> Result<DecodeResult<T>, String> {
93 match codec_prefix::get(encoded_data){
94 Some(codec::CodecType::JSON)=>{
95 let wout_prefix = codec_prefix::remove(encoded_data);
96
97 match serde_json::from_slice(wout_prefix) {
98 Ok(data) => Ok(DecodeResult { codec: codec::CodecType::JSON, data }),
99 Err(err) => Err(format!("Could not deserialize the given data. Serde error: {:?}", err))
100 }
101 },
102 None => Err(String::from("Could not deserialize the given data, the codec at the beginning is unknown"))
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[derive(Serialize, Deserialize)]
111 struct TestObject {
112 message: String
113 }
114
115 #[test]
116 fn encoding_decoding_works(){
117 let test_object=TestObject{message:String::from("Live long and prosper")};
118 let encoded=encode(codec::CodecType::JSON, &test_object);
119 assert_eq!(encoded.is_ok(),true);
120
121 let decoded:DecodeResult<TestObject>=decode(encoded.unwrap().as_ref()).unwrap();
122 assert_eq!(decoded.data.message, test_object.message);
123 assert_eq!(decoded.codec,codec::CodecType::JSON);
124 }
125}