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
//! Compound data types.

#![allow(non_snake_case)]

macro_rules! itemize(($($chunk:item)*) => ($($chunk)*));

macro_rules! table {
    ($(#[$attribute:meta])* pub $structure:ident {
        $($field:ident ($($kind:tt)+) $(|$($argument:ident),+| $body:block)*,)+
    }) => (
        define_table! { $(#[$attribute])* pub $structure { $($field ($($kind)+),)+ } }
        read_table! { pub $structure { $($field ($($kind)+) $(|$($argument),+| $body)*,)+ } }
    );
}

macro_rules! define_table {
    ($(#[$attribute:meta])* pub $structure:ident { $($field:ident ($kind:ty),)+ }) => (itemize! {
        $(#[$attribute])*
        #[derive(Clone, Debug, Default, Eq, PartialEq)]
        pub struct $structure { $(pub $field: $kind,)+ }
    });
}

macro_rules! read_table {
    (pub $structure:ident {
        $($field:ident ($($kind:tt)+) $(|$($argument:ident),+| $body:block)*,)+
    }) => (
        impl ::tape::Value for $structure {
            fn read<T: ::tape::Tape>(tape: &mut T) -> ::Result<Self> {
                let mut table = $structure::default();
                $(
                    table.$field = read_field!($structure, tape, table, [$($kind)+]
                                               $(|$($argument),+| $body)*);
                )+
                Ok(table)
            }
        }
    );
}

macro_rules! read_field(
    ($structure:ident, $tape:ident, $table:ident,
     [$kind:ty] |$pipe:ident, $chair:ident| $body:block) => ({
        #[inline(always)]
        #[allow(unused_variables)]
        fn read<T: ::tape::Tape>($pipe: &mut T, $chair: &$structure) -> ::Result<$kind> $body
        try!(read($tape, &$table))
    });
    ($structure:ident, $tape:expr, $table:expr, [$kind:ty]) => ({
        try!(::tape::Value::read($tape))
    });
);

macro_rules! read_vector(
    ($tape:ident, $count:expr, i8) => (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");
        }
        Ok(::std::mem::transmute(values))
    });
    ($tape:ident, $count:expr, u8) => (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");
        }
        Ok(values)
    });
    ($tape:ident, $count:expr) => ({
        let count = $count as usize;
        let mut values = Vec::with_capacity(count);
        for _ in 0..count {
            values.push(try!(::tape::Value::read($tape)));
        }
        Ok(values)
    });
);

mod char_mapping;
mod font_header;
mod horizontal_header;
mod horizontal_metrics;
mod maximum_profile;
mod naming_table;
mod offset_table;
mod postscript;
mod windows_metrics;

pub use self::char_mapping::{CharMapping, CharMappingHeader, CharMappingRecord};
pub use self::char_mapping::{CharMappingEncoding, CharMappingEncoding4, CharMappingEncoding6};
pub use self::font_header::FontHeader;
pub use self::horizontal_header::HorizontalHeader;
pub use self::horizontal_metrics::{HorizontalMetrics, LongHorizontalMetric};
pub use self::maximum_profile::{MaximumProfile, MaximumProfile05, MaximumProfile10};
pub use self::naming_table::{NameRecord, LanguageTagRecord};
pub use self::naming_table::{NamingTable, NamingTable0, NamingTable1};
pub use self::offset_table::{OffsetTable, OffsetTableHeader, OffsetTableRecord};
pub use self::postscript::{PostScript, PostScript10, PostScript30};
pub use self::windows_metrics::{WindowsMetrics, WindowsMetrics3, WindowsMetrics5};