marc 0.2.4

Reader and builder for MARC 21 Bibliographic format
Documentation
use std::borrow::Borrow;
use std::borrow::ToOwned;
use std::char;
use std::io;
use std::io::Read;
use std::io::Error;
use std::io::ErrorKind::Other;
use std::slice;
use std::str;

const MIN_REC_LEN: u32 = 24;
const MAX_REC_LEN: u32 = 99_999;
const RECORD_TERMINATOR: u8 = 0x1D;
const FIELD_TERMINATOR: u8 = 0x1E;
const SUBFIELD_DELIMITER: u8 = 0x1F;

/// Field representation.
pub type FieldRepr = (Tag, Vec<u8>);

/// Subfield representation.
pub type SubfieldRepr = (Identifier, Vec<u8>);

/// Field tag representation.
///
/// `Into<Tag>` are implemented for `&[u8]`, `&str`, `[u8; 3]` and `Tag`.
///
/// `From<&Tag>` are implemented for `&[u8]`, `&str`, `[u8; 3]` and `&Tag`.
#[derive(Eq, PartialEq, Ord, PartialOrd,
         Clone, Hash, Debug)]
pub struct Tag([u8; 3]);

/// Data field indicator representation.
#[derive(Eq, PartialEq, Ord, PartialOrd,
         Clone, Hash, Debug)]
pub struct Indicator([u8; 2]);

/// Subfield identifier representation.
#[derive(Eq, PartialEq, Ord, PartialOrd,
         Clone, Copy, Hash, Debug)]
pub struct Identifier(u8);

/// Reference to a data of a field.
pub struct FieldData<'a>(&'a [u8]);

// -> (tag, field_len, start_pos)
type DirectoryEntry = (Tag, u32, u32);

impl Borrow<[u8]> for Tag {
    fn borrow(&self) -> &[u8] {
        let &Tag(ref tag) = self;
        tag
    }
}

impl<'a> Borrow<[u8]> for FieldData<'a> {
    fn borrow(&self) -> &[u8] {
        let &FieldData(ref data) = self;
        data
    }
}

impl<'a> From<&'a [u8]> for Tag {
    fn from(s: &'a [u8]) -> Tag {
        assert!(s.len() == 3, "Tag length != 3");
        Tag([s[0], s[1], s[2]])
    }
}

impl<'a> From<&'a str> for Tag {
    fn from(s: &'a str) -> Tag {
        s.as_bytes().into()
    }
}

impl From<[u8; 3]> for Tag {
    fn from(s: [u8; 3]) -> Tag {
        Tag(s)
    }
}

impl<'a> From<&'a Tag> for &'a str {
    fn from(tag: &'a Tag) -> &'a str {
        str::from_utf8(tag.borrow()).unwrap()
    }
}

impl<'a> From<&'a Tag> for &'a [u8] {
    fn from(tag: &'a Tag) -> &'a [u8] {
        tag.borrow()
    }
}

impl<'a> From<&'a Tag> for [u8; 3] {
    fn from(tag: &'a Tag) -> [u8; 3] {
        let Tag(x) = tag.clone();
        x
    }
}

/// Entities that can be created from data of a field or a subfield.
pub trait FromFieldData {
    fn from_data(data: &[u8]) -> Option<&Self>;
}

impl FromFieldData for [u8] {
    #[inline]
    fn from_data(data: &[u8]) -> Option<&[u8]> {
        Some(data)
    }
}

impl FromFieldData for str {
    #[inline]
    fn from_data(data: &[u8]) -> Option<&str> {
        str::from_utf8(data).ok()
    }
}

impl From<Identifier> for u8 {
    fn from(Identifier(x): Identifier) -> u8 {
        x
    }
}

impl From<Identifier> for char {
    fn from(Identifier(x): Identifier) -> char {
        char::from_u32(x as u32).unwrap()
    }
}

impl From<u8> for Identifier {
    fn from(x: u8) -> Identifier {
        Identifier(x)
    }
}

impl From<char> for Identifier {
    fn from(x: char) -> Identifier {
        assert_eq!(x.len_utf8(), 1);
        let mut dst = String::with_capacity(1);
        dst.push(x);
        Identifier(AsRef::<str>::as_ref(&dst).as_bytes()[0])
    }
}

impl Borrow<[u8]> for Indicator {
    fn borrow(&self) -> &[u8] {
        let &Indicator(ref ind) = self;
        ind
    }
}

impl From<Indicator> for [u8; 2] {
    fn from(Indicator(ind): Indicator) -> [u8; 2] {
        ind
    }
}

impl From<Indicator> for [char; 2] {
    fn from(Indicator(ind): Indicator) -> [char; 2] {
        [char::from_u32(ind[0] as u32).unwrap(), char::from_u32(ind[1] as u32).unwrap()]
    }
}

impl From<[char; 2]> for Indicator {
    fn from(bs: [char; 2]) -> Indicator {
        assert_eq!(bs[0].len_utf8(), 1);
        assert_eq!(bs[1].len_utf8(), 1);
        let mut dst = String::with_capacity(2);
        dst.push(bs[0]);
        dst.push(bs[1]);
        let bytes = AsRef::<str>::as_ref(&dst).as_bytes();
        Indicator([bytes[0], bytes[1]])
    }
}

impl From<[u8; 2]> for Indicator {
    fn from(bs: [u8; 2]) -> Indicator {
        Indicator(bs)
    }
}

impl<'a> From<Field<'a>> for FieldRepr {
    fn from(Field {tag, data}: Field<'a>) -> FieldRepr {
        (tag, data.to_owned())
    }
}

impl<'a> From<Subfield<'a>> for SubfieldRepr {
    fn from(sf: Subfield<'a>) -> SubfieldRepr {
        (sf.ident, sf.data.to_owned())
    }
}

trait LeaderField {
    fn from_byte(byte: u8) -> Self;
    fn to_byte(&self) -> u8;
}

macro_rules! read_exact(
    ($source:expr, $dest:expr, 1, $edesc:expr) => ({
        match $source.read(&mut $dest) {
            Ok(c) => {
                if c == 1 {
                    Ok(())
                } else {
                    Err(Error::new(Other, $edesc))
                }
            },
            Err(e) => Err(e),
        }
    });
    ($source:expr, $dest:expr, $count:expr, $edesc:expr) => ({
        let mut rc = $count;
        let mut err = None;
        loop {
            match $source.read(&mut $dest[($count - rc)..rc]) {
                Ok(c) => {
                    if c == rc {
                        break;
                    } else if c == 0 {
                        err = Some(Error::new(Other, $edesc));
                        break
                    }
                    rc -= c;
                },
                Err(e) => {
                    err = Some(e);
                    break;
                }
            }
        }
        if err.is_some() {
            Err(err.unwrap())
        } else {
            Ok(())
        }
    });
);

trait MrcWriteInternal: io::Write {
    fn write_dec_num(&mut self, len: u8, mut value: u32) -> io::Result<()> {
        let mut buf = [0x30u8; 10];
        for i in 0u8..len {
            buf[len as usize - i as usize - 1] = (value % 10) as u8 + 0x30;
            value = value / 10;
            if value == 0 {
                break;
            }
        }
        self.write_all(&(&buf)[0..len as usize])
    }
}

impl<T: io::Write + ?Sized> MrcWriteInternal for T {}

trait MrcReadInternal: io::Read {
    #[inline]
    fn read_leader_field<T: LeaderField>(&mut self) -> io::Result<T> {
        let mut buf = [0u8];
        try!(read_exact!(self, buf, 1, "Unexpected EOF while reading leader field"));
        Ok(T::from_byte(buf[0]))
    }
    fn read_dec_num(&mut self, len: u8) -> io::Result<u32> {
        assert!(0 < len && len < 11);
        let mut buf = [0u8; 11];
        try!(read_exact!(self, buf, len as usize, "Unexpected EOF while reading decimal number"));
        let mut res = 0u32;
        let mut pos = len;
        for &i in &buf[..(len as usize)] {
            if b'0' > i || i > b'9' {
                return Err(Error::new(Other, "Unexpected byte while reading decimal number"));
            }
            let mut x = (i - 0x30) as u32;
            if pos > 0 {
                if x != 0 {
                    for _ in 1..pos {
                        x *= 10
                    }
                }
                pos -= 1;
            }
            res += x;
        }
        Ok(res)
    }
    // -> (tag, field_len, start_pos)
    fn read_directory_entry(&mut self) -> io::Result<DirectoryEntry> {
        let mut tag = [0u8; 3];
        try!(read_exact!(self, tag, 3, "Unexpected EOF while reading directory entry"));
        let field_len = try!(self.read_dec_num(4));
        let start_pos = try!(self.read_dec_num(5));
        Ok((Tag(tag), field_len, start_pos))
    }
}

impl<T: io::Read + ?Sized> MrcReadInternal for T {}

/// io::Read extension which provides `read_record` method.
pub trait MrcRead: io::Read {
    fn read_record(&mut self) -> io::Result<Option<Record>> {
        let mut rec = io::Cursor::new(Vec::with_capacity(5));

        match self.take(5).read_to_end(rec.get_mut()) {
            Ok(0) => return Ok(None),
            Ok(x) if x < 5 => {
                return Err(Error::new(Other, "Unexpected EOF while reading record length"))
            },
            Err(e) => return Err(e),
            _ => (),
        }

        let record_length = try!(rec.read_dec_num(5));
        if MIN_REC_LEN > record_length || record_length > MAX_REC_LEN {
            return Err(Error::new(Other, "Record length is out of bounds"));
        }

        rec.get_mut().reserve(record_length as usize - 5);
        match self.take(record_length as u64 - 5).read_to_end(rec.get_mut()) {
            Ok(x) if x < record_length as usize - 5 => {
                return Err(Error::new(Other, "Unexpected EOF while reading record"));
            },
            Err(e) => return Err(e),
            _ => (),
        }
        if rec.get_ref()[rec.get_ref().len()-1] != RECORD_TERMINATOR {
            return Err(Error::new(Other, "No record terminator"));
        }

        let record = try!(Record::from_data(rec.into_inner()));
        Ok(Some(record))
    }
}

impl<T: io::Read + ?Sized> MrcRead for T {}

#[derive(Debug, PartialEq, Clone)]
pub enum Warning {
    WrongIndicatorCount(u8),
    WrongSubfieldCodeCount(u8),
    WrongLengthOfFieldLen(u8),
    WrongStartingCharacterPositionLen(u8),
    WrongImplementationDefinedPortionLen(u8),
}

/// Iterator over fields of a record.
#[derive(Clone)]
pub struct Fields<'a> {
    record: &'a Record,
    vec_iter: slice::Iter<'a, DirectoryEntry>,
    remain: u32,
}

impl<'a> Iterator for Fields<'a> {
    type Item = Field<'a>;

    fn next(&mut self) -> Option<Field<'a>> {
        if let Some(entry) = self.vec_iter.next() {
            self.remain -= 1;
            Some(Field::from_entry(self.record, entry))
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.remain as usize, Some(self.remain as usize))
    }
}

#[derive(Debug, PartialEq, Clone)]
/// Borrowed version of a field of a record.
pub struct Field<'a> {
    data: &'a [u8],
    tag: Tag,
}

impl<'a> Field<'a> {
    fn from_entry<'r>(rec: &'r Record, entry: &DirectoryEntry) -> Field<'r> {
        let begin = (rec.base_address_of_data + entry.2) as usize;
        let end = begin + entry.1 as usize;
        Field {
            data: &rec.data[begin..end],
            tag: entry.0.clone(),
        }
    }

    /// Returns true if `self` is data field.
    #[inline]
    pub fn is_data_field(&self) -> bool {
        self.data[2] == SUBFIELD_DELIMITER
    }

    /// Returns true if `self` is control field.
    #[inline]
    pub fn is_control_field(&self) -> bool {
        ! self.is_data_field()
    }

    /// Returns subfields with identifier `ident` or empty vec if no such subfields.
    pub fn get_subfield<'f, T: Into<Identifier>>(&'f self, ident: T) -> Vec<Subfield<'f>> {
        let mut res = Vec::new();
        if self.is_data_field() && self.data.len() > 2 {
            let ident: Identifier = ident.into();
            let mut start = None;
            for (i, &x) in self.data.iter().enumerate() {
                if i < 2 {
                    continue;
                }
                if start.is_none() {
                    if self.data[i-1] == SUBFIELD_DELIMITER {
                        if x == ident.into() {
                            start = Some(i - 1);
                        }
                    }
                } else {
                    if x == SUBFIELD_DELIMITER || x == FIELD_TERMINATOR {
                        res.push(Subfield {
                            data: &self.data[start.unwrap()..i],
                            tag: self.tag.clone(),
                            ident: ident,
                        });
                        start = None
                    }
                }
            }
        }
        res
    }

    /// Returns iterator over subfields of a data field.
    #[inline]
    pub fn subfields<'f>(&'f self) -> Subfields<'f> {
        Subfields::new(self.clone())
    }

    /// Returns indictor of data field or `None` if self is control field.
    #[inline]
    pub fn get_indicator<T: From<Indicator>>(&self) -> Option<T> {
        if self.is_data_field() {
            Some(From::from([self.data[0], self.data[1]].into()))
        } else {
            None
        }
    }

    /// Returns data of a control field or `None` if self is data field.
    #[inline]
    pub fn get_data<T: FromFieldData + ?Sized>(&self) -> Option<&T> {
        if ! self.is_data_field() && self.data.len() > 1 {
            FromFieldData::from_data(&self.data[0..(self.data.len()-1)])
        } else {
            None
        }
    }

    /// Returns tag of a field.
    #[inline]
    pub fn get_tag<T: From<&'a Tag>>(&'a self) -> T {
        From::from(&self.tag)
    }
}

/// Iterator over subfields of a data field.
#[derive(Clone)]
pub struct Subfields<'a> {
    field: Field<'a>,
    offset: usize,
    start: Option<usize>,
    ident: Option<Identifier>,
    remain: u32,
}

impl<'a> Subfields<'a> {
    fn new(field: Field<'a>) -> Subfields<'a> {
        let mut subfields = Subfields {
            field: field,
            offset: 0,
            start: None,
            ident: None,
            remain: 0,
        };
        subfields.count_subfields();
        subfields
    }

    fn count_subfields(&mut self) {
        for &x in self.field.data.iter() {
            if x == SUBFIELD_DELIMITER {
                self.remain += 1;
            }
        }
    }
}

impl<'a> Iterator for Subfields<'a> {
    type Item = Subfield<'a>;

    fn next(&mut self) -> Option<Subfield<'a>> {
        if self.field.is_control_field() || self.field.data[self.offset] == FIELD_TERMINATOR {
            None
        } else if self.start.is_none() {
            for (i, &x) in (&self.field.data[self.offset..]).iter().enumerate() {
                if (self.offset + i) < 2 {
                    continue;
                }
                if x == SUBFIELD_DELIMITER {
                    self.start = Some(self.offset+i);
                    self.ident = Some(self.field.data[self.offset+i+1].into());
                    self.offset += i + 1;
                    break;
                } else if x == FIELD_TERMINATOR {
                    return None;
                }
            }
            self.next()
        } else {
            let mut subfield = None;
            let start = self.start.take().unwrap();
            for (i, &x) in (&self.field.data[self.offset..]).iter().enumerate() {
                if x == SUBFIELD_DELIMITER || x == FIELD_TERMINATOR {
                    self.offset += i - 1;
                    self.remain -= 1;
                    subfield = Some(Subfield {
                        data: &self.field.data[start..start+i+1],
                        tag: self.field.tag.clone(),
                        ident: self.ident.take().unwrap(),
                    });
                    break;
                }
            }
            subfield
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.remain as usize, Some(self.remain as usize))
    }
}

#[derive(Debug, PartialEq, Clone)]
/// Borrowed version of a subfield of a data field.
pub struct Subfield<'a> {
    data: &'a [u8],
    tag: Tag,
    ident: Identifier,
}

impl<'a> Subfield<'a> {
    /// Returns identifier of a subfield.
    #[inline]
    pub fn get_identifier<T: From<Identifier>>(&self) -> T {
        From::from(self.ident)
    }

    /// Returns data of a subfield.
    #[inline]
    pub fn get_data<T: FromFieldData + ?Sized>(&self) -> Option<&T> {
        if self.data.len() > 2 {
            FromFieldData::from_data(&self.data[2..self.data.len()])
        } else {
            None
        }
    }

    /// Returns tag of a field `self` belongs to.
    #[inline]
    pub fn get_tag<T: From<&'a Tag>>(&'a self) -> T {
        From::from(&self.tag)
    }
}

/// Allows you to build MARC variable data fields.
pub struct DataFieldBuilder {
    tag: Tag,
    indicator: Indicator,
    subfields: Vec<SubfieldRepr>,
    size: u32,
}

impl DataFieldBuilder {
    pub fn new<T, I, S>(tag: T, indicator: I, subfield: S) -> DataFieldBuilder
    where T: Into<Tag> + Clone, I: Into<Indicator>, S: Into<SubfieldRepr> {
        let tag = tag.clone().into();
        let indicator = indicator.into();
        let subfield = subfield.into();
        let mut res = DataFieldBuilder {
            tag: tag,
            indicator: indicator,
            subfields: Vec::new(),
            size: 2 + subfield.1.len() as u32 + 1,
        };
        res.subfields.insert(0, subfield);
        res
    }
    pub fn add_subfield<T: Into<SubfieldRepr>>(mut self, subfield: T) -> DataFieldBuilder {
        let subfield = subfield.into();
        self.size += subfield.1.len() as u32;
        let mut index = 0;
        for (i, sf) in self.subfields.iter().enumerate() {
            if sf.0 >= subfield.0 {
                index = i;
                break;
            }
        }
        self.subfields.insert(index, subfield);
        self
    }
    /// Removes all subfields with identifier `ident`.
    pub fn remove_subfield<T: Into<Identifier>>(mut self, ident: T) -> DataFieldBuilder {
        let ident = ident.into();
        self.subfields.retain(|subfield| {
            subfield.0 != ident
        });
        self
    }
    pub fn into_field_repr(self) -> FieldRepr {
        let tag = self.tag;
        let mut data = Vec::with_capacity(self.size as usize);
        {
            // XXX: Wait for Vec::push_all
            let Indicator(ref ind) = self.indicator;
            data.push(ind[0]);
            data.push(ind[1])
        }
        for (ident, subfiled_data) in self.subfields.into_iter() {
            data.push(ident.into());
            data.extend(subfiled_data);
        }
        data.push(FIELD_TERMINATOR);
        (tag, data)
    }
}

/// Allows you to build MARC records.
pub struct RecordBuilder {
    record_status: RecordStatus,
    type_of_record: TypeOfRecord,
    bibliographic_level: BibliographicLevel,
    type_of_control: TypeOfControl,
    character_coding_scheme: CharacterCodingScheme,
    encoding_level: EncodingLevel,
    descriptive_cataloging_form: DescriptiveCatalogingForm,
    multipart_resource_record_level: MultipartResourceRecordLevel,
    fields: Vec<FieldRepr>,
    size: u32,
}

impl RecordBuilder {
    pub fn new() -> RecordBuilder {
        RecordBuilder {
            record_status: RecordStatus::IncreaseInEncodingLevel,
            type_of_record: TypeOfRecord::LanguageMaterial,
            bibliographic_level: BibliographicLevel::MonographicComponentPart,
            type_of_control: TypeOfControl::NoSpecifiedType,
            character_coding_scheme: CharacterCodingScheme::Marc8,
            encoding_level: EncodingLevel::FullLevel,
            descriptive_cataloging_form: DescriptiveCatalogingForm::NonIsbd,
            multipart_resource_record_level: MultipartResourceRecordLevel::NotSpecifiedOrNotApplicable,
            fields: Vec::new(),
            size: 24,
        }
    }
    pub fn from_record(rec: &Record) -> RecordBuilder {
        let mut res = RecordBuilder {
            record_status: rec.record_status.clone(),
            type_of_record: rec.type_of_record.clone(),
            bibliographic_level: rec.bibliographic_level.clone(),
            type_of_control: rec.type_of_control.clone(),
            character_coding_scheme: rec.character_coding_scheme.clone(),
            encoding_level: rec.encoding_level.clone(),
            descriptive_cataloging_form: rec.descriptive_cataloging_form.clone(),
            multipart_resource_record_level: rec.multipart_resource_record_level.clone(),
            fields: Vec::new(),
            size: 24,
        };
        for field in rec.fields() {
            res = res.add_field(field);
        }
        res
    }
    #[inline]
    pub fn set_record_status(mut self, x: RecordStatus) -> RecordBuilder {
        self.record_status = x; self
    }
    #[inline]
    pub fn set_type_of_record(mut self, x: TypeOfRecord) -> RecordBuilder {
        self.type_of_record = x; self
    }
    #[inline]
    pub fn set_bibliographic_level(mut self, x: BibliographicLevel) -> RecordBuilder {
        self.bibliographic_level = x; self
    }
    #[inline]
    pub fn set_type_of_control(mut self, x: TypeOfControl) -> RecordBuilder {
        self.type_of_control = x; self
    }
    #[inline]
    pub fn set_character_coding_scheme(mut self, x: CharacterCodingScheme) -> RecordBuilder {
        self.character_coding_scheme = x; self
    }
    #[inline]
    pub fn set_encoding_level(mut self, x: EncodingLevel) -> RecordBuilder {
        self.encoding_level = x; self
    }
    #[inline]
    pub fn set_descriptive_cataloging_form(mut self, x: DescriptiveCatalogingForm) -> RecordBuilder {
        self.descriptive_cataloging_form = x; self
    }
    #[inline]
    pub fn set_multipart_resource_record_level(mut self, x: MultipartResourceRecordLevel) -> RecordBuilder {
        self.multipart_resource_record_level = x; self
    }
    pub fn add_field<T: Into<FieldRepr>>(mut self, def: T) -> RecordBuilder {
        let repr = def.into();
        let mut index = 0;
        self.size += repr.1.len() as u32 + 12;
        for (i, f) in self.fields.iter().enumerate() {
            if f.0 >= repr.0 {
                index = i;
                break;
            }
        }
        self.fields.insert(index, repr);
        self
    }
    /// Removes all fields with tag `tag`.
    pub fn remove_field<T: Into<Tag> + Clone>(mut self, tag: T) -> RecordBuilder {
        let tag = tag.into();
        self.fields.retain(|field| {
            field.0 != tag
        });
        self
    }
    pub fn into_record(self) -> Record {
        let mut data = Vec::with_capacity(self.size as usize);
        let _ = data.write_dec_num(5, self.size);
        let _ = io::Write::write_all(&mut data, &[
            self.record_status.to_byte(),
            self.type_of_record.to_byte(),
            self.bibliographic_level.to_byte(),
            self.type_of_control.to_byte(),
            self.character_coding_scheme.to_byte(),
            b'2',
            b'2',
        ]);
        let _ = data.write_dec_num(5, 24 + 12 * self.fields.len() as u32 + 1);
        let _ = io::Write::write_all(&mut data, &[
            self.encoding_level.to_byte(),
            self.descriptive_cataloging_form.to_byte(),
            self.multipart_resource_record_level.to_byte(),
            b'4',
            b'5',
            b'0',
            b'0',
        ]);
        let mut offset = 0;
        for field_repr in self.fields.iter() {
            let _ = io::Write::write_all(&mut data, field_repr.0.borrow());
            let _ = data.write_dec_num(4, field_repr.1.len() as u32);
            let _ = data.write_dec_num(5, offset);
            offset += field_repr.1.len() as u32;
        }
        data.push(FIELD_TERMINATOR);
        for (_, field_data) in self.fields.into_iter() {
            data.extend(field_data);
        }
        data.push(RECORD_TERMINATOR);
        Record::from_data(data).unwrap()
    }
}

#[derive(Debug, PartialEq, Clone)]
/// Parsed MARC record representation.
pub struct Record {
    length: u32,
    base_address_of_data: u32,
    indicator_count: u8,
    subfield_code_count: u8,
    length_of_field_len: u8,
    starting_character_position_len: u8,
    implementation_defined_portion_len: u8,
    pub record_status: RecordStatus,
    pub type_of_record: TypeOfRecord,
    pub bibliographic_level: BibliographicLevel,
    pub type_of_control: TypeOfControl,
    pub character_coding_scheme: CharacterCodingScheme,
    pub encoding_level: EncodingLevel,
    pub descriptive_cataloging_form: DescriptiveCatalogingForm,
    pub multipart_resource_record_level: MultipartResourceRecordLevel,
    warnings: Vec<Warning>,
    data: Vec<u8>,
    directory_entryes: Option<Vec<DirectoryEntry>>,
}

impl Record {
    pub fn from_vec(data: Vec<u8>) -> io::Result<Record> {
        let record_length = try!((&data[..]).read_dec_num(5));
        if record_length as usize != data.len() {
            return Err(Error::new(Other, "Vector length does not equals record length"));
        }

        if data[data.len() - 1] != RECORD_TERMINATOR {
            return Err(Error::new(Other, "Record does not ends with record terminator"));
        }

        Record::from_data(data)
    }
    fn from_data(data: Vec<u8>) -> io::Result<Record> {
        let mut rec = io::Cursor::new(data);
        let record_length = try!(rec.read_dec_num(5));
        let mut warnings = Vec::new();
        let record_status = try!(rec.read_leader_field());
        let type_of_record = try!(rec.read_leader_field());
        let bibliographic_level = try!(rec.read_leader_field());
        let type_of_control = try!(rec.read_leader_field());
        let character_coding_scheme = try!(rec.read_leader_field());
        let indicator_count = try!(rec.read_dec_num(1)) as u8;
        if indicator_count != 2 {
            warnings.push(Warning::WrongIndicatorCount(indicator_count));
        }
        let subfield_code_count = try!(rec.read_dec_num(1)) as u8;
        if subfield_code_count != 2 {
            warnings.push(Warning::WrongSubfieldCodeCount(subfield_code_count));
        }
        let base_address_of_data = try!(rec.read_dec_num(5));
        let encoding_level = try!(rec.read_leader_field());
        let descriptive_cataloging_form = try!(rec.read_leader_field());
        let multipart_resource_record_level = try!(rec.read_leader_field());
        let length_of_field_len = try!(rec.read_dec_num(1)) as u8;
        if length_of_field_len != 4 {
            warnings.push(Warning::WrongLengthOfFieldLen(length_of_field_len));
        }
        let starting_character_position_len = try!(rec.read_dec_num(1)) as u8;
        if starting_character_position_len != 5 {
            warnings.push(
                Warning::WrongStartingCharacterPositionLen(starting_character_position_len));
        }
        let implementation_defined_portion_len = try!(rec.read_dec_num(1)) as u8;
        if implementation_defined_portion_len != 0 {
            warnings.push(
                Warning::WrongImplementationDefinedPortionLen(implementation_defined_portion_len));
        }

        let mut record = Record {
            length: record_length,
            base_address_of_data: base_address_of_data,
            indicator_count: indicator_count,
            subfield_code_count: subfield_code_count,
            length_of_field_len: length_of_field_len,
            starting_character_position_len: starting_character_position_len,
            implementation_defined_portion_len: implementation_defined_portion_len,
            record_status: record_status,
            type_of_record: type_of_record,
            bibliographic_level: bibliographic_level,
            type_of_control: type_of_control,
            character_coding_scheme: character_coding_scheme,
            encoding_level: encoding_level,
            descriptive_cataloging_form: descriptive_cataloging_form,
            multipart_resource_record_level: multipart_resource_record_level,
            warnings: warnings,
            data: rec.into_inner(),
            directory_entryes: None,
        };
        try!(record.parse_directory());
        Ok(record)
    }

    /// Returns iterator over fields of a record.
    #[inline]
    pub fn fields<'r>(&'r self) -> Fields<'r> {
        Fields {
            record: self,
            vec_iter: self.directory_entryes.as_ref().unwrap().iter(),
            remain: self.directory_entryes.as_ref().unwrap().len() as u32,
        }
    }

    /// Returns fileds with tag `tag` or empty vec if no such fields.
    pub fn get_field<'r, T: Into<Tag> + Clone>(&'r self, tag: T) -> Vec<Field<'r>> {
        let tag = tag.into();
        let mut field = Vec::new();
        for x in self.directory_entryes.as_ref().unwrap().iter() {
            if x.0 == tag {
                field.push(Field::from_entry(self, x));
            }
        }
        field
    }

    /// Returns a slice into data of a field.
    #[inline]
    pub fn as_slice(&self) -> &[u8] {
        &self.data[..]
    }

    fn parse_directory(&mut self) -> io::Result<()> {
        let mut directory_entryes_count = 0;
        for i in 0..(self.data.len() - 24) {
            if self.data[i] == FIELD_TERMINATOR {
                directory_entryes_count = i / 12;
            }
        }
        let mut directory_entryes = Vec::with_capacity(directory_entryes_count);
        let mut dir = io::Cursor::new(& self.data[24..]);
        while dir.get_ref()[dir.position() as usize] != FIELD_TERMINATOR {
            directory_entryes.push(try!(dir.read_directory_entry()));
        }
        self.directory_entryes = Some(directory_entryes);
        Ok(())
    }
}

macro_rules! leader_field(
    ($name:ident {
        $($val:expr => $kind:ident,)+
    }) => (
        #[derive(Debug, PartialEq, Clone)]
        pub enum $name {
            $($kind),+,
            Unknown(u8),
        }

        impl LeaderField for $name {
            #[inline]
            fn from_byte(byte: u8) -> $name {
                match byte {
                    $($val => $name::$kind),+,
                    b => $name::Unknown(b),
                }
            }
            #[inline]
            fn to_byte(&self) -> u8 {
                match *self {
                    $($name::$kind => $val),+,
                    $name::Unknown(b) => b,
                }
            }
        }
    );
);

leader_field! {
    RecordStatus {
        b'a' => IncreaseInEncodingLevel,
        b'c' => CorrectedOrRevised,
        b'd' => Deleted,
        b'n' => New,
        b'p' => IncreaseInEncodingLevelFromPrepublication,
    }
}

leader_field! {
    TypeOfRecord {
        b'a' => LanguageMaterial,
        b'c' => NotatedMusic,
        b'd' => ManuscriptNotatedMusic,
        b'e' => CartographicMaterial,
        b'f' => ManuscriptCartographicMaterial,
        b'g' => ProjectedMedium,
        b'i' => NonmusicalSoundRecording,
        b'j' => MusicalSoundRecording,
        b'k' => TwoDimensionalNonprojectableGraphic,
        b'm' => ComputerFile,
        b'o' => Kit,
        b'p' => MixedMaterials,
        b'r' => ThreeDimensionalArtifactOrNaturallyOccurringObject,
        b't' => ManuscriptLanguageMaterial,
    }
}

leader_field! {
    BibliographicLevel {
        b'a' => MonographicComponentPart,
        b'b' => SerialComponentPart,
        b'c' => Collection,
        b'd' => Subunit,
        b'i' => IntegratingResource,
        b'm' => MonographOrItem,
        b's' => Serial,
    }
}

leader_field! {
    TypeOfControl {
        b' ' => NoSpecifiedType,
        b'a' => Archival,
    }
}

leader_field! {
    CharacterCodingScheme {
        b' ' => Marc8,
        b'a' => UcsUnicode,
    }
}

leader_field! {
    EncodingLevel {
        b' ' => FullLevel,
        b'1' => FullLevelMaterialNotExamined,
        b'2' => LessThanFullLevelMaterialNotExamined,
        b'3' => AbbreviatedLevel,
        b'4' => CoreLevel,
        b'5' => PartialLevel,
        b'7' => MinimalLevel,
        b'8' => PrepublicationLevel,
        b'u' => UnknownEL,
        b'z' => NotApplicable,
    }
}

leader_field! {
    DescriptiveCatalogingForm {
        b' ' => NonIsbd,
        b'a' => Aacr2,
        b'c' => IsbdPunctuationOmitted,
        b'i' => IsbdPunctuationIncluded,
        b'u' => UnknownDCF,
    }
}

leader_field! {
    MultipartResourceRecordLevel {
        b' ' => NotSpecifiedOrNotApplicable,
        b'a' => Set,
        b'b' => PartWithIndependentTitle,
        b'c' => PartWithDependentTitle,
    }
}

#[cfg(test)]
mod tests {
    const RECS: &'static str = "00963nam a2200229 i 4500001001000000003000800010003000800018005001700026008004100043035002300084040002600107041000800133072001900141100005800160245028000218260004000498300001600538650004200554856010400596979001200700979002100712\x1e000000001\x1eRuMoRGB\x1eEnMoRGB\x1e20080528120000.0\x1e080528s1992    ru a|||  a    |00 u rus d\x1e  \x1fa(RuMoEDL)-92k71098\x1e  \x1faRuMoRGB\x1fbrus\x1fcRuMoRGB\x1e0 \x1farus\x1e 7\x1fa07.00.03\x1f2nsnr\x1e1 \x1fa'Абд Ал-'Азиз Джа'фар Бин 'Акид\x1e00\x1faЭтносоциальная структура и институты социальной защиты в Хадрамауте (19 - первая половина 20 вв.) :\x1fbавтореферат дис. ... кандидата исторических наук : 07.00.03\x1e  \x1faСанкт-Петербург\x1fc1992\x1e  \x1fa24 c.\x1fbил\x1e 7\x1faВсеобщая история\x1f2nsnr\x1e41\x1fqapplication/pdf\x1fuhttp://dlib.rsl.ru/rsl01000000000/rsl01000000000/rsl01000000001/rsl01000000001.pdf\x1e  \x1faautoref\x1e  \x1fbautoreg\x1fbautoreh\x1e\x1d\
                                00963nam a2200229 i 4500001001000000003000800010003000800018005001700026008004100043035002300084040002600107041000800133072001900141100005800160245028000218260004000498300001600538650004200554856010400596979001200700979002100712\x1e000000002\x1eRuMoRGB\x1eEnMoRGB\x1e20080528120000.0\x1e080528s1992    ru a|||  a    |00 u rus d\x1e  \x1fa(RuMoEDL)-92k71098\x1e  \x1faRuMoRGB\x1fbrus\x1fcRuMoRGB\x1e0 \x1farus\x1e 7\x1fa07.00.03\x1f2nsnr\x1e1 \x1fa'Абд Ал-'Азиз Джа'фар Бин 'Акид\x1e00\x1faЭтносоциальная структура и институты социальной защиты в Хадрамауте (19 - первая половина 20 вв.) :\x1fbавтореферат дис. ... кандидата исторических наук : 07.00.03\x1e  \x1faСанкт-Петербург\x1fc1992\x1e  \x1fa24 c.\x1fbил\x1e 7\x1faВсеобщая история\x1f2nsnr\x1e41\x1fqapplication/pdf\x1fuhttp://dlib.rsl.ru/rsl01000000000/rsl01000000000/rsl01000000002/rsl01000000002.pdf\x1e  \x1faautoref\x1e  \x1fbautoreg\x1fbautoreh\x1e\x1d";
    const FIELDS_COUNT: usize = 17;
    mod read {
        use super::RECS;
        use super::FIELDS_COUNT;
        use super::super::*;

        #[test]
        fn records() {
            let mut recs = RECS.as_bytes();
            let rec1 = recs.read_record().unwrap().unwrap();
            assert_eq!(rec1.data, &RECS.as_bytes()[0..rec1.data.len()]);
            assert_eq!(rec1.data.len(), 963);
            let rec2 = recs.read_record().unwrap().unwrap();
            assert_eq!(rec2.data.len(), 963);
            assert_eq!(rec2.data, &RECS.as_bytes()[rec1.data.len()..]);
            assert_eq!(None, recs.read_record().unwrap());
        }

        #[test]
        fn from_vec() {
            use std::borrow::ToOwned;

            let vec = (& RECS.as_bytes()[0..963]).to_owned();
            let rec = Record::from_vec(vec).unwrap();
            assert_eq!(rec.data, &RECS.as_bytes()[0..rec.data.len()]);
            assert_eq!(rec.data.len(), 963);
        }

        #[test]
        fn fields_iterator() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            let mut fields = rec.fields();
            let hint = fields.size_hint();
            assert_eq!(hint.0, *hint.1.as_ref().unwrap());
            assert_eq!(hint.0, FIELDS_COUNT);
            let mut count = 0;
            while let Some(field) = fields.next() {
                count += 1;
                let hint = fields.size_hint();
                assert_eq!(hint.0, *hint.1.as_ref().unwrap());
                assert_eq!(hint.0, FIELDS_COUNT - count);
                match count {
                    01 => assert_eq!(Some(field.get_tag()), Some("001")),
                    02 => assert_eq!(Some(field.get_tag()), Some("003")),
                    03 => assert_eq!(Some(field.get_tag()), Some("003")),
                    04 => assert_eq!(Some(field.get_tag()), Some("005")),
                    05 => assert_eq!(Some(field.get_tag()), Some("008")),
                    06 => assert_eq!(Some(field.get_tag()), Some("035")),
                    07 => assert_eq!(Some(field.get_tag()), Some("040")),
                    08 => assert_eq!(Some(field.get_tag()), Some("041")),
                    09 => assert_eq!(Some(field.get_tag()), Some("072")),
                    10 => assert_eq!(Some(field.get_tag()), Some("100")),
                    11 => assert_eq!(Some(field.get_tag()), Some("245")),
                    12 => assert_eq!(Some(field.get_tag()), Some("260")),
                    13 => assert_eq!(Some(field.get_tag()), Some("300")),
                    14 => assert_eq!(Some(field.get_tag()), Some("650")),
                    15 => assert_eq!(Some(field.get_tag()), Some("856")),
                    16 => assert_eq!(Some(field.get_tag()), Some("979")),
                    17 => assert_eq!(Some(field.get_tag()), Some("979")),
                    _ => assert!(false),
                }
            }
        }

        #[test]
        fn control_field() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            assert_eq!(rec.get_field("001").len(), 1);
            assert!(rec.get_field("001")[0].is_control_field());
            assert_eq!(rec.get_field("001")[0].data, b"000000001\x1e");
            assert_eq!(Some(rec.get_field("001")[0].get_tag()), Some(&b"001"[..]));
            assert_eq!(rec.get_field("001")[0].get_data(), Some(&b"000000001"[..]));
            assert_eq!(Some(rec.get_field("001")[0].get_tag()), Some("001"));
            assert_eq!(rec.get_field("001")[0].get_data(), Some("000000001"));
        }

        #[test]
        fn control_fields() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            assert_eq!(rec.get_field("003").len(), 2);
            assert!(rec.get_field("003")[0].is_control_field());
            assert_eq!(rec.get_field("003")[0].data, b"RuMoRGB\x1e");
            assert_eq!(Some(rec.get_field("003")[0].get_tag()), Some(&b"003"[..]));
            assert_eq!(rec.get_field("003")[0].get_data(), Some(&b"RuMoRGB"[..]));
            assert_eq!(Some(rec.get_field("003")[0].get_tag()), Some("003"));
            assert_eq!(rec.get_field("003")[0].get_data(), Some("RuMoRGB"));
            assert!(rec.get_field("003")[1].is_control_field());
            assert_eq!(rec.get_field("003")[1].data, b"EnMoRGB\x1e");
            assert_eq!(Some(rec.get_field("003")[1].get_tag()), Some(&b"003"[..]));
            assert_eq!(rec.get_field("003")[1].get_data(), Some(&b"EnMoRGB"[..]));
            assert_eq!(Some(rec.get_field("003")[1].get_tag()), Some("003"));
            assert_eq!(rec.get_field("003")[1].get_data(), Some("EnMoRGB"));
        }

        #[test]
        fn data_field() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            assert_eq!(rec.get_field("856").len(), 1);
            assert!(rec.get_field("856")[0].is_data_field());
            assert_eq!(Some(rec.get_field("856")[0].get_tag()), Some("856"));
            assert_eq!(rec.get_field("856")[0].data, &b"41\x1fqapplication/pdf\x1fuhttp://dlib.rsl.ru/rsl01000000000/rsl01000000000/rsl01000000001/rsl01000000001.pdf\x1e"[..]);
            assert_eq!(rec.get_field("856")[0].get_indicator(), Some(['4', '1']));
        }

        #[test]
        fn data_fields() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            assert_eq!(rec.get_field("979").len(), 2);
            assert!(rec.get_field("979")[0].is_data_field());
            assert_eq!(Some(rec.get_field("979")[0].get_tag()), Some("979"));
            assert_eq!(rec.get_field("979")[0].data, b"  \x1faautoref\x1e");
            assert_eq!(rec.get_field("979")[0].get_indicator(), Some([' ', ' ']));
            assert!(rec.get_field("979")[1].is_data_field());
            assert_eq!(Some(rec.get_field("979")[1].get_tag()), Some("979"));
            assert_eq!(rec.get_field("979")[1].data, b"  \x1fbautoreg\x1fbautoreh\x1e");
            assert_eq!(rec.get_field("979")[1].get_indicator(), Some([' ', ' ']));
        }

        #[test]
        fn subfields_iterator() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            let ref field = rec.get_field("979")[0];
            let mut subfields = field.subfields();
            let hint = subfields.size_hint();
            assert_eq!(hint.0, *hint.1.as_ref().unwrap());
            assert_eq!(hint.0, 1);
            let mut count = 0;
            while let Some(subfield) = subfields.next() {
                count += 1;
                let hint = subfields.size_hint();
                assert_eq!(hint.0, *hint.1.as_ref().unwrap());
                assert_eq!(hint.0, 0);
                match count {
                    01 => {
                        assert_eq!(subfield.get_identifier::<char>(), 'a');
                        assert_eq!(subfield.get_data(), Some("autoref"));
                    },
                    _ => assert!(false),
                }
            }
            let ref field = rec.get_field("979")[1];
            let mut subfields = field.subfields();
            let hint = subfields.size_hint();
            assert_eq!(hint.0, *hint.1.as_ref().unwrap());
            assert_eq!(hint.0, 2);
            let mut count = 0;
            while let Some(subfield) = subfields.next() {
                count += 1;
                let hint = subfields.size_hint();
                assert_eq!(hint.0, *hint.1.as_ref().unwrap());
                assert_eq!(hint.0, 2 - count);
                match count {
                    01 => {
                        assert_eq!(subfield.get_identifier::<char>(), 'b');
                        assert_eq!(subfield.get_data(), Some("autoreg"));
                    },
                    02 => {
                        assert_eq!(subfield.get_identifier::<char>(), 'b');
                        assert_eq!(subfield.get_data(), Some("autoreh"));
                    },
                    _ => assert!(false),
                }
            }
        }

        #[test]
        fn subfield() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            let ref field = rec.get_field("979")[0];
            assert_eq!(field.get_subfield('a').len(), 1);
            assert_eq!(field.get_subfield('a')[0].data, b"\x1faautoref");
            assert_eq!(Some(field.get_subfield('a')[0].get_tag()), Some("979"));
            assert_eq!(field.get_subfield('a')[0].get_identifier::<char>(), 'a');
            assert_eq!(field.get_subfield('a')[0].get_data(), Some("autoref"));
        }

        #[test]
        fn subfields() {
            let rec = RECS.as_bytes().read_record().unwrap().unwrap();
            let ref field = rec.get_field("979")[1];
            assert_eq!(field.get_subfield('b').len(), 2);
            assert_eq!(field.get_subfield('b')[0].data, b"\x1fbautoreg");
            assert_eq!(Some(field.get_subfield('b')[0].get_tag()), Some("979"));
            assert_eq!(field.get_subfield('b')[0].get_identifier::<char>(), 'b');
            assert_eq!(field.get_subfield('b')[0].get_data(), Some("autoreg"));
            assert_eq!(field.get_subfield('b')[1].data, b"\x1fbautoreh");
            assert_eq!(Some(field.get_subfield('b')[1].get_tag()), Some("979"));
            assert_eq!(field.get_subfield('b')[1].get_identifier::<char>(), 'b');
            assert_eq!(field.get_subfield('b')[1].get_data(), Some("autoreh"));
        }
    }
}