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}