/// /// Generic record-level read/write functionality. /// use std::io::Write; use std::convert::TryInto; use byteorder::{ByteOrder, BigEndian}; use crate::basic::{pack_datetime, pack_bitarray, pack_ascii, pack_int2, pack_int4, pack_real8}; #[warn(unused_imports)] use crate::basic::{parse_datetime, parse_bitarray, parse_ascii, parse_int2, parse_int4, parse_real8}; #[warn(unused_imports)] use crate::basic::{OResult, IResult, fail, parse_u16, take_bytes}; //ErrType, use crate::records; //#[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 read(input: &[u8]) -> IResult { let (input, size) = parse_u16(input)?; let (input, tag) = parse_u16(input)?; Ok((input, RecordHeader{tag, data_size:size - 4})) } pub fn pack_into(&self) -> [u8; 4] { assert!(self.data_size < 0xffff - 4, "Record too big!"); let vals = [self.data_size, self.tag]; let mut buf = [0x77; 4]; BigEndian::write_u16_into(&vals, &mut buf); buf } pub fn write(&self, ww: &mut W) -> OResult { let bytes = self.pack_into(); ww.write(&bytes) } } pub trait RecordData { type BareData<'a>; type InData : ?Sized; type ByteData : AsRef<[u8]>; fn read(input: &[u8], size: u16) -> IResult>; fn pack_into(buf: &mut [u8], data: &Self::InData); //fn size(data: &Self::BareData<'_>) -> u16; fn pack(data: &Self::InData) -> Self::ByteData; } pub trait Record { fn tag() -> u16; fn expected_size() -> Option; fn check_size(actual_size: u16) -> Result<(), String> { match Self::expected_size() { Some(size) => if size == actual_size { Ok(()) } else { Err(format!("Expected record size {}, got {}", size, actual_size)) }, None => Ok(()), } } fn read_header(input: &[u8]) -> IResult { RecordHeader::read(input) } fn write_header(ww: &mut W, data_size: u16) -> OResult { RecordHeader{tag: Self::tag(), data_size}.write(ww) } fn read_data(input: &[u8], size: u16) -> IResult> { RData::read(input, size) } fn pack_data(buf: &mut [u8], data: &RData::InData) { RData::pack_into(buf, data) } /// /// 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. /// fn skip_past(input: &[u8]) -> IResult { let original_input = input; let (mut input, mut header) = RecordHeader::read(input)?; while header.tag != Self::tag() { (input, _) = take_bytes(input, header.data_size)?; if header.tag == records::RTAG_ENDLIB { return Ok((original_input, false)) } (input, header) = RecordHeader::read(input)?; } (input, _) = take_bytes(input, header.data_size)?; Ok((input, true)) } fn skip_and_read(input: &[u8]) -> IResult> { let (mut input, mut header) = RecordHeader::read(input)?; while header.tag != Self::tag() { (input, _) = take_bytes(input, header.data_size)?; (input, header) = RecordHeader::read(input)?; } let (input, data) = Self::read_data(input, header.data_size)?; Ok((input, data)) } fn expect_header(input: &[u8]) -> IResult { let (input, header) = RecordHeader::read(input)?; if header.tag != Self::tag() { fail(input, format!("Unexpected record! Got tag 0x{:04x}, expected 0x{:04x}", header.tag, Self::tag())) } else { Ok((input, header.data_size)) } } fn read(input: &[u8]) -> IResult> { let (input, size) = Self::expect_header(input)?; Self::check_size(size).unwrap(); let (input, data) = Self::read_data(input, size)?; Ok((input, data)) } fn write(ww: &mut W, data: &RData::InData) -> OResult { let packed_data = RData::pack(data); let data_bytes = packed_data.as_ref(); let len: u16 = data_bytes.len().try_into().expect("Record longer than max size (u16)!"); let mut size = 0; size += Self::write_header(ww, len)?; size += ww.write(data_bytes)?; Ok(size) } } pub struct BitArray; impl RecordData for BitArray { type BareData<'a> = [bool; 16]; type InData = [bool; 16]; type ByteData = [u8; 2]; fn read(input: &[u8], size: u16) -> IResult> { assert!(size == 2); parse_bitarray(input) } fn pack_into(buf: &mut [u8], data: &Self::InData) { pack_bitarray(buf, data); } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = [0; 2]; Self::pack_into(&mut buf, data); buf } } pub struct Int2; impl RecordData for Int2 { type BareData<'a> = i16; type InData = i16; type ByteData = [u8; 2]; fn read(input: &[u8], size: u16) -> IResult> { assert!(size == 2); parse_int2(input) } fn pack_into(buf: &mut [u8], data: &Self::InData) { pack_int2(buf, *data) } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = [0; 2]; Self::pack_into(&mut buf, data); buf } } pub struct Int4; impl RecordData for Int4 { type BareData<'a> = i32; type InData = i32; type ByteData = [u8; 4]; fn read(input: &[u8], size: u16) -> IResult> { assert!(size == 4); parse_int4(input) } fn pack_into(buf: &mut [u8], data: &Self::InData) { pack_int4(buf, *data) } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = [0; 4]; Self::pack_into(&mut buf, data); buf } } pub struct Int2Array; impl RecordData for Int2Array { type BareData<'a> = Int2ArrayReader<'a>; type InData = [i16]; type ByteData = Vec; fn read(input: &[u8], size: u16) -> IResult> { assert!(size % 2 == 0, "Record must contain an integer quantity of integers"); //let mut input = input; let (input, bytes) = take_bytes(input, size)?; Ok((input, Int2ArrayReader{bytes})) } fn pack_into(buf: &mut [u8], data: &Self::InData) { BigEndian::write_i16_into(data, buf) } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = Vec::with_capacity(data.len() * 2); Self::pack_into(&mut buf, data); buf } } pub struct Int2ArrayReader<'a> { bytes: &'a [u8], } impl Iterator for Int2ArrayReader<'_> { type Item = i16; fn next(&mut self) -> Option { if self.bytes.len() < 2 { None } else { let (remaining, val) = parse_int2(self.bytes).unwrap(); self.bytes = remaining; Some(val) } } } pub struct Int4Array; impl RecordData for Int4Array { type BareData<'a> = Int4ArrayReader<'a>; type InData = [i32]; type ByteData = Vec; fn read(input: &[u8], size: u16) -> IResult> { assert!(size % 4 == 0, "Record must contain an integer quantity of integers"); //let mut input = input; let (input, bytes) = take_bytes(input, size)?; Ok((input, Int4ArrayReader{bytes})) } fn pack_into(buf: &mut [u8], data: &Self::InData) { BigEndian::write_i32_into(data, buf) } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = Vec::with_capacity(data.len() * 4); Self::pack_into(&mut buf, data); buf } } pub struct Int4ArrayReader<'a> { bytes: &'a [u8], } impl Iterator for Int4ArrayReader<'_> { type Item = i32; fn next(&mut self) -> Option { if self.bytes.len() < 4 { None } else { let (remaining, val) = parse_int4(self.bytes).unwrap(); self.bytes = remaining; Some(val) } } } pub struct Real8; impl RecordData for Real8 { type BareData<'a> = f64; type InData = f64; type ByteData = [u8; 8]; fn read(input: &[u8], size: u16) -> IResult> { assert!(size == 8); parse_real8(input) } fn pack_into(buf: &mut [u8], data: &Self::InData) { pack_real8(buf, *data).unwrap_or_else(|_| panic!("Float {0} too big for Real8", data)) } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = [0; 8]; Self::pack_into(&mut buf, data); buf } } pub struct Real8Pair; impl RecordData for Real8Pair { type BareData<'a> = (f64, f64); type InData = (f64, f64); type ByteData = [u8; 2 * 8]; fn read(input: &[u8], size: u16) -> IResult> { assert!(size == 2 * 8); let (input, data0) = parse_real8(input)?; let (input, data1) = parse_real8(input)?; Ok((input, (data0, data1))) } fn pack_into(buf: &mut [u8], data: &Self::InData) { pack_real8(&mut buf[8 * 0..], data.0).unwrap_or_else(|_| panic!("Float.0 {0} too big for Real8", data.0)); pack_real8(&mut buf[8 * 1..], data.1).unwrap_or_else(|_| panic!("Float.1 {0} too big for Real8", data.1)); } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = [0; 2 * 8]; Self::pack_into(&mut buf, data); buf } //fn write(ww: &mut W, data: &Self::BareData) -> OResult { // let mut buf = [u8; 2 * 6 * 2]; // Self::pack_into(&mut buf, data) //} } pub struct ASCII; impl RecordData for ASCII { type BareData<'a> = Vec; type InData = [u8]; type ByteData = Vec; fn read(input: &[u8], size: u16) -> IResult> { parse_ascii(input, size) } fn pack_into(buf: &mut [u8], data: &Self::InData) { pack_ascii(buf, data); } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = Vec::with_capacity(data.len() * 4); Self::pack_into(&mut buf, data); buf } } pub struct DateTimePair; impl RecordData for DateTimePair { type BareData<'a> = [[i16; 6]; 2]; type InData = [[i16; 6]; 2]; type ByteData = [u8; 2 * 6 * 2]; fn read(input: &[u8], size: u16) -> IResult> { assert!(size == 2 * 6 * 2); let (input, data0) = parse_datetime(input)?; let (input, data1) = parse_datetime(input)?; Ok((input, [data0, data1])) } fn pack_into(buf: &mut [u8], data: &Self::InData) { pack_datetime(&mut buf[6 * 2 * 0..], &data[0]); pack_datetime(&mut buf[6 * 2 * 1..], &data[1]); } fn pack(data: &Self::InData) -> Self::ByteData { let mut buf = [0; 2 * 6 * 2]; Self::pack_into(&mut buf, data); buf } //fn write(ww: &mut W, data: &Self::BareData) -> OResult { // let mut buf = [u8; 2 * 6 * 2]; // Self::pack_into(&mut buf, data) //} } pub struct Empty; impl RecordData for Empty { type BareData<'a> = (); type InData = (); type ByteData = [u8; 0]; fn read(input: &[u8], size: u16) -> IResult> { assert!(size == 0); Ok((input, ())) } fn pack_into(_buf: &mut [u8], _data: &Self::InData) { } fn pack(_data: &Self::InData) -> Self::ByteData { [] } //fn write(ww: &mut W, data: &Self::BareData) { //} }