1#[macro_export]
51macro_rules! union_formatter {
52 (#[target($buffer:ty)]
53 enum $name:ident : $key_type:ty {
54 $($key_value:expr; $case_name:ident($field_type:ty)),*
55 }) => {
56 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
57 pub enum $name {
58 $($case_name($field_type)),*
59 }
60
61 impl Formatter<$name> for $buffer {
62
63 fn serialize(&mut self, offset: u64, value: $name) -> ZeroFormatterResult<i32> {
64 let mut byte_size: i32 = 4;
65
66 match value {
67 $(
68 $name::$case_name(v) => {
69 byte_size += try!(self.serialize(offset + (byte_size as u64), $key_value));
70 byte_size += try!(self.serialize(offset + (byte_size as u64), v))
71 }
72 ),*
73 }
74
75 try!(self.serialize(offset, byte_size));
76
77 Ok(byte_size)
78 }
79
80 fn deserialize(&mut self, offset: &mut u64) -> ZeroFormatterResult<$name> {
81
82 try!(util::check_non_null(self, offset));
83
84 let key: $key_type = try!(self.deserialize(offset));
85 match key {
86 $(
87 $key_value => {
88 let v: $field_type = try!(self.deserialize(offset));
89 Ok( $name::$case_name (v) )
90 }
91 ),*,
92 _ => ZeroFormatterError::invalid_binary(*offset)
93 }
94 }
95 }
96
97 option_formatter! {
98 #[target($buffer)]
99 $name
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106
107 use std::io::Cursor;
108 use std::io::{Seek, SeekFrom};
109 use error::*;
110 use formatter::*;
111 use util;
112
113 object_formatter! {
114 #[target(Cursor<Vec<u8>>)]
115 O {
116 0; a: i32
117 }
118 }
119
120 struct_formatter! {
121 #[target(Cursor<Vec<u8>>)]
122 S {
123 b: i64
124 }
125 }
126
127 union_formatter! {
128 #[target(Cursor<Vec<u8>>)]
129 enum U: i32 {
130 1; A(O),
131 2; B(S)
132 }
133 }
134
135 #[test]
136 fn serialize_deserialize_union_a() {
137 let mut c = Cursor::new(Vec::new());
138 let input: U = U::A(O{ a: 1 });
139 assert_eq!(c.serialize(0, input).unwrap(), 24);
140 let mut offset = 0;
141 assert_eq!(input, c.deserialize(&mut offset).unwrap());
142 }
143
144 #[test]
145 fn serialize_deserialize_union_b() {
146 let mut c = Cursor::new(Vec::new());
147 let input: U = U::B(S{ b: 2 });
148 assert_eq!(c.serialize(0, input).unwrap(), 16);
149 let mut offset = 0;
150 assert_eq!(input, c.deserialize(&mut offset).unwrap());
151 }
152}