/* * Generic record-level read/write functionality. */ use nom::IResult; use std::io::Write; use byteorder::BigEndian; use basic::{pack_datetime, pack_bitarray, pack_ascii, pack_int2, pack_int4, pack_real8}; #[warn(unused_imports)] use basic::{parse_datetime, parse_bitarray, parse_ascii, parse_int2, parse_int4, parse_real8}; #[warn(unused_imports)] use basic::{OWResult}; use records; //from .basic import parse_int2, parse_int4, parse_real8, parse_datetime, parse_bitarray //from .basic import pack_int2, pack_int4, pack_real8, pack_datetime, pack_bitarray //from .basic import parse_ascii, read //#[no_mangle] //pub extern "C" fn write_record_header( #[repr(C)] pub struct RecordHeader { pub tag: u16, pub data_size: u16, } impl RecordHeader { pub fn parse(input: &[u8]) -> IResult<&[u8], RecordHeader> { let (_, size) = nom::number::streaming::be_u16(input[0..])?; let (_, tag) = nom::number::streaming::be_u16(input[2..])?; Ok((input[4..], RecordHeader{tag:tag, data_size:size - 4})) } pub fn pack(self) -> [u8; 4] { assert!(self.size < 0xffff - 4, "Record too big!"); let vals = [self.size, self.tag]; let mut buf = [0x77; 4]; BigEndian::write_u16_into(&vals, &mut buf); buf } pub fn write(&self, ww: W) -> OWResult { let bytes = self.pack(); ww.write(bytes) } } pub trait Record { fn tag() -> u32; fn expected_size() -> Option; //fn parse_data(input: &[u8], size: usize) -> IResult<&[u8], Self>; } impl Record { pub fn check_size(&self, actual_size: usize) -> Result<(), &str> { match self.expected_size() { Some(size) => if size == actual_size { Ok(()) } else { Err(format!("Expected record size {}, got {}", size, actual_size)) }, None => Ok(()), } } pub fn parse_header(input: &[u8]) -> IResult<&[u8], RecordHeader> { RecordHeader::parse(input) } pub fn write_header(ww: W, data_size: usize) -> OWResult { RecordHeader{tag: Self.tag(), size: data_size}.write(ww) } pub fn skip_past(input: &[u8]) -> IResult<&[u8], bool> { /* * Skip to the end of the next occurence of this record. * * Return: * True if the record was encountered and skipped. * False if the end of the library was reached. */ let (input, header) = RecordHeader::parse(input)?; while header.tag != Self.tag() { let (input, _) = nom::bytes::streaming::take(header.size)?; if header.tag == records::RTAG_ENDLIB { return Ok((input, false)) } let (input, header) = RecordHeader::parse(input)?; } let (input, _) = nom::bytes::streaming::take(header.size)?; Ok((input, true)) } /* pub fn skip_and_read(input: &[u8]) -> IResult<&[u8], bool>{ size, tag = Record.read_header(stream) while tag != cls.tag{ stream.seek(size, io.SEEK_CUR) size, tag = Record.read_header(stream) } data = cls.read_data(stream, size) return data } def read(cls: Type[R], stream: BinaryIO){ size = expect_record(stream, cls.tag) data = cls.read_data(stream, size) return data } def write(cls, stream: BinaryIO, data) -> int { data_bytes = cls.pack_data(data) b = cls.write_header(stream, len(data_bytes)) b += stream.write(data_bytes) return b } */ } pub trait BitArray { fn parse_data(input: &[u8]) -> IResult<&[u8], [bool; 16]> { parse_bitarray(input) } fn pack_data(buf: &mut [u8], vals: &[bool; 16]) { pack_bitarray(&mut buf, vals) } } pub trait Int2 { fn parse_data(input: &[u8]) -> IResult<&[u8], i16> { parse_int2(input) } fn pack_data(buf: &mut [u8], val: i16) { pack_int2(&mut buf, val) } } pub trait Int4 { fn parse_data(input: &[u8]) -> IResult<&[u8], i32> { parse_int4(input) } fn pack_data(buf: &mut [u8], val: i32) { pack_int4(&mut buf, val) } } pub trait Int2Array { fn parse_data(input: &[u8], size: usize) -> IResult<&[u8], Vec> { assert!(size % 2 == 0, "Record must contain an integer quantity of integers"); nom::multi::count(parse_int2, size / 2)(input) } fn pack_data(buf: &mut [u8], vals: &[i16]) { BigEndian::write_i16_into(&vals, &mut buf) } } pub trait Int4Array { fn parse_data(input: &[u8], size: usize) -> IResult<&[u8], Vec> { assert!(size % 4 == 0, "Record must contain an integer quantity of integers"); nom::multi::count(parse_int4, size / 4)(input) } fn pack_data(buf: &mut [u8], vals: &[i32]) { BigEndian::write_i32_into(&vals, &mut buf) } } pub trait Real8 { fn parse_data(input: &[u8]) -> IResult<&[u8], f64> { parse_real8(input) } fn pack_data(buf: &mut [u8], val: f64) { pack_real8(&mut buf, val) } } pub trait ASCII { fn parse_data(input: &[u8]) -> IResult<&[u8], Vec> { parse_ascii(input) } fn pack_data(buf: &mut [u8], data: &[u8]) { pack_ascii(&mut buf, data) } } pub trait DateTime { fn parse_data(input: &[u8]) -> IResult<&[u8], [u16; 6]> { parse_datetime(input) } fn pack_data(buf: &mut [u8], data: [u16; 6]) { pack_datetime(&mut buf, data) } } impl DTR { fn skip_and_read(input: &[u8]) -> IResult<&[u8], [DTR; 2]> { let mut header = Self.read_header(input)?; while header.tag != Self.tag() { nom::bytes::streaming::take(header.data_size)?; header = Self.read_header(input)?; } assert!(header.data_size == 6 * 2); let data0 = Self.read_data(&input)?; let data1 = Self.read_data(&input)?; Ok([data0, data1]) } }