1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
use error::*; use formatter::*; use std::io::Seek; use byteorder::{ReadBytesExt, WriteBytesExt}; use chrono::{UTC, DateTime}; use std::time::Duration; #[macro_export] macro_rules! has_value_formatter_methods { ($t:ty) => ( fn serialize(&mut self, offset: u64, value: Option<$t>) -> ZeroFormatterResult<i32> { match value { None => { self.serialize(offset, false) }, Some(v) => { let r1 = try!(self.serialize(offset, true)); let r2 = try!(self.serialize(offset + 1, v)); Ok(r1 + r2) } } } fn deserialize(&mut self, offset: &mut u64) -> ZeroFormatterResult<Option<$t>> { let has_value: bool = try!(self.deserialize(offset)); if has_value { self.deserialize(offset).map(|v| Some(v)) } else { Ok(None) } } ) } macro_rules! primitive_has_value_formatter { ($($t:ty),*) => ($( impl<R> Formatter<Option<$t>> for R where R: Seek + ReadBytesExt + WriteBytesExt { has_value_formatter_methods! { $t } } )*) } primitive_has_value_formatter! { u8, u16, u32, u64, i8, i16, i32, i64, f32, f64, bool, DateTime<UTC>, Duration } #[macro_export] macro_rules! has_value_formatter { (#[target($buffer:ty)] $t:ty ) => ( impl Formatter<Option<$t>> for $buffer { has_value_formatter_methods! { $t } } ) } #[cfg(test)] mod tests { use std::io::Cursor; use formatter::*; #[test] fn serialize_u8_some() { let mut wtr = Cursor::new(Vec::new()); assert_eq!(wtr.serialize(0, Some(1u8)).unwrap(), 2); assert_eq!(wtr.into_inner(), vec![1, 1]); } #[test] fn deserialize_u8_some() { let mut rdr = Cursor::new(vec![1, 1]); let mut offset = 0; assert_eq!(Some(1u8), rdr.deserialize(&mut offset).unwrap()); } #[test] fn serialize_u8_none() { let mut wtr = Cursor::new(Vec::new()); let input: Option<u8> = None; assert_eq!(wtr.serialize(0, input).unwrap(), 1); assert_eq!(wtr.into_inner(), vec![0]); } #[test] fn deserialize_u8_none() { let mut rdr = Cursor::new(vec![0]); let mut offset = 0; let expected: Option<u8> = None; assert_eq!(expected, rdr.deserialize(&mut offset).unwrap()); } }