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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
macro_rules! deref { ($name:ident::$field:tt => $target:ty) => (itemize! { impl ::std::ops::Deref for $name { type Target = $target; #[inline] fn deref(&self) -> &Self::Target { &self.$field } } impl ::std::ops::DerefMut for $name { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.$field } } }); } macro_rules! flags { ($(#[$attribute:meta])* pub $structure:ident($kind:ident) { $($mask:expr => $name:ident,)* }) => ( $(#[$attribute])* #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct $structure(pub $kind); impl $structure { $( #[inline(always)] pub fn $name(&self) -> bool { self.0 & $mask > 0 } )* } impl ::Value for $structure { #[inline(always)] fn read<T: ::Tape>(tape: &mut T) -> ::Result<Self> { Ok($structure(read_value!(tape, $kind))) } } impl From<$structure> for $kind { #[inline(always)] fn from(flags: $structure) -> $kind { flags.0 } } ); } macro_rules! itemize(($($chunk:item)*) => ($($chunk)*)); macro_rules! raise( ($message:expr) => (return Err(::Error::new(::std::io::ErrorKind::Other, $message))); ($($argument:tt)+) => (raise!(format!($($argument)+))); ); macro_rules! read_bytes( ($tape:ident, $count:expr) => (unsafe { let count = $count as usize; let mut values = Vec::with_capacity(count); values.set_len(count); if try!(::std::io::Read::read($tape, &mut values)) != count { return raise!("failed to read as much as needed"); } values }); ); macro_rules! read_field( ($structure:ident, $tape:ident, $table:ident, [$kind:ty] |$band:ident, $chair:ident| $body:block) => ({ #[allow(unused_variables)] #[inline(always)] fn read<T: ::Tape>($band: &mut T, $chair: &$structure) -> ::Result<$kind> $body try!(read($tape, &$table)) }); ($structure:ident, $tape:ident, $table:expr, [$kind:ty]) => (read_value!($tape)); ); macro_rules! read_value( ($tape:expr) => (try!(::Value::read($tape))); ($tape:expr, $kind:ty) => (try!(<$kind as ::Value>::read($tape))); ); macro_rules! read_walue( ($tape:expr, $parameter:expr) => (try!(::Walue::read($tape, $parameter))); ($tape:expr, $parameter:expr, $kind:ty) => ({ try!(<$kind as ::Walue<_>>::read($tape, $parameter)) }); ); macro_rules! table { ($(#[$attribute:meta])* pub $structure:ident { $($field:ident ($($kind:tt)+) $(|$($argument:ident),+| $body:block)*,)* }) => ( table! { @define $(#[$attribute])* pub $structure { $($field ($($kind)+),)* } } table! { @implement pub $structure { $($field ($($kind)+) $(|$($argument),+| $body)*,)* } } ); (@define $(#[$attribute:meta])* pub $structure:ident { $($field:ident ($kind:ty),)* }) => (itemize! { $(#[$attribute])* #[derive(Clone, Debug, Eq, PartialEq)] pub struct $structure { $(pub $field: $kind,)* } }); (@implement pub $structure:ident { $($field:ident ($($kind:tt)+) $(|$($argument:ident),+| $body:block)*,)* }) => ( impl ::Value for $structure { fn read<T: ::Tape>(tape: &mut T) -> ::Result<Self> { let mut table: $structure = unsafe { ::std::mem::uninitialized() }; $({ let value = read_field!($structure, tape, table, [$($kind)+] $(|$($argument),+| $body)*); ::std::mem::forget(::std::mem::replace(&mut table.$field, value)); })* Ok(table) } } ); }