use content::Content;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Read, Write, Result, Error, ErrorKind};
use hash::NewHash;
use backend::Backend;
impl<T> Content for Option<T> where T: Content {
fn to_content(
&self,
sink: &mut Write,
backend: &mut Backend,
) -> Result<()> {
match *self {
Some(ref t) => {
try!(sink.write(&[1]));
t.to_content(sink, backend)
},
None => sink.write_all(&[0])
}
}
fn from_content(
source: &mut Read,
newhash: &NewHash,
) -> Result<Self> {
let mut byte = [0];
try!(source.read_exact(&mut byte));
match byte[0] {
0 => Ok(None),
1 => Ok(Some(try!(T::from_content(source, newhash)))),
_ => Err(Error::new(
ErrorKind::Other, "Invalid Option<T> encoding!")
),
}
}
}
impl<T> Content for Box<T> where T: Content {
fn to_content(
&self,
sink: &mut Write,
backend: &mut Backend,
) -> Result<()> {
(self as &T).to_content(sink, backend)
}
fn from_content(
source: &mut Read,
newhash: &NewHash,
) -> Result<Self> {
Ok(Box::new(try!(T::from_content(source, newhash))))
}
}
impl Content for u8 {
fn to_content(&self, sink: &mut Write, _: &mut Backend) -> Result<()> {
sink.write_all(&[*self])
}
fn from_content(source: &mut Read, _: &NewHash) -> Result<Self> {
let b = &mut [0u8];
try!(source.read_exact(b));
Ok(b[0])
}
}
macro_rules! number {
( $t:ty: $read:ident, $write:ident ) => {
impl Content for $t {
fn to_content(
&self,
sink: &mut Write,
_: &mut Backend,
) -> Result<()> {
sink.$write::<BigEndian>(*self)
}
fn from_content(
source: &mut Read,
_: &NewHash,
) -> Result<Self> {
source.$read::<BigEndian>()
}
}
}
}
number!(u64: read_u64, write_u64);
number!(u32: read_u32, write_u32);
number!(u16: read_u16, write_u16);
#[cfg(test)]
mod tests {
use test_common;
use content::Content;
use std::fmt::Debug;
fn put_get<T: Content + Debug + PartialEq>(t: T) {
let mut store = test_common::store();
let hash = store.put(&t).unwrap();
assert_eq!(store.get(&hash).unwrap(), t);
}
#[test]
fn std() {
put_get(Some(46u64));
put_get(None as Option<u64>);
put_get(38u64);
}
}