diff --git a/Cargo.toml b/Cargo.toml index a211306..d878d23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,4 @@ crate-type = ["cdylib", "rlib"] [dependencies] byteorder = "^1" +arrow = "*" diff --git a/src/elements.rs b/src/elements.rs index b711da2..479ea3b 100644 --- a/src/elements.rs +++ b/src/elements.rs @@ -3,7 +3,8 @@ /// structure references) and associated properties. /// -use crate::records::{BOX, BOUNDARY, NODE, PATH, TEXT, SREF, AREF, +use crate::records::{ + //BOX, BOUNDARY, NODE, PATH, TEXT, SREF, AREF, DATATYPE, PATHTYPE, BOXTYPE, NODETYPE, TEXTTYPE, LAYER, XY, WIDTH, COLROW, PRESENTATION, STRING, STRANS, MAG, ANGLE, PROPATTR, PROPVALUE, @@ -12,10 +13,550 @@ use crate::records::{BOX, BOUNDARY, NODE, PATH, TEXT, SREF, AREF, use crate::records; use crate::record::{RecordHeader, Record}; -use crate::basic::{OResult, IResult, fail}; +use crate::basic::{IResult, fail, take_bytes}; //OResult +use std::string::String; use std::collections::HashMap; -use std::io::Write; +//use std::io::Write; + +use std::sync::Arc; +use arrow::datatypes::{DataType, Field, Fields}; +use arrow::array::{ + StructBuilder, ListBuilder, StringBuilder, ArrayBuilder, Float64Builder, BooleanBuilder, + Int32Builder, Int16Builder, UInt64Builder, UInt32Builder, UInt8Builder, + StructArray, + }; + + +type DListBuilder = ListBuilder>; + + +pub fn read_library(input: &[u8]) -> IResult { + let input_size = input.len(); + + let property_t = DataType::Struct(Fields::from(vec![ + Field::new("key", DataType::Int16, false), + Field::new("value", DataType::Utf8, false), + ])); + + let property_list_t = DataType::List(Arc::new( + Field::new_list_field(property_t, false) + )); + + + let repetition_struct_t = DataType::Struct(Fields::from(vec![ + Field::new("x0", DataType::Int32, false), + Field::new("y0", DataType::Int32, false), + Field::new("x1", DataType::Int32, false), + Field::new("y1", DataType::Int32, false), + Field::new("count0", DataType::Int16, false), + Field::new("count1", DataType::Int16, false), + ])); + + + let ref_struct_t = DataType::Struct(Fields::from(vec![ + Field::new("target", DataType::UInt32, false), + Field::new("invert_y", DataType::Boolean, true), + Field::new("mag", DataType::Float64, true), + Field::new("angle_deg", DataType::Float64, true), + Field::new("x", DataType::Int32, false), + Field::new("y", DataType::Int32, false), + Field::new("repetition", repetition_struct_t, true), + Field::new("properties", property_list_t.clone(), true), + ])); + + + let text_struct_t = DataType::Struct(Fields::from(vec![ + Field::new("layer", DataType::UInt16, false), + Field::new("dtype", DataType::UInt16, false), + Field::new("presentation_horiz", DataType::UInt8, true), + Field::new("presentation_vert", DataType::UInt8, true), + Field::new("presentation_font", DataType::UInt8, true), + Field::new("path_type", DataType::Int16, true), + Field::new("width", DataType::Int32, true), + Field::new("invert_y", DataType::Boolean, true), + Field::new("mag", DataType::Float64, true), + Field::new("angle_deg", DataType::Float64, true), + Field::new("x", DataType::Int32, false), + Field::new("y", DataType::Int32, false), + Field::new("string", DataType::Utf8, false), + Field::new("properties", property_list_t.clone(), true), + ])); + + + let coords_t = DataType::List(Arc::new( + Field::new_list_field(DataType::Int32, false) + )); + + let boundary_struct_t = DataType::Struct(Fields::from(vec![ + Field::new("layer", DataType::UInt16, false), + Field::new("dtype", DataType::UInt16, false), + Field::new("xy", coords_t.clone(), false), + Field::new("properties", property_list_t.clone(), true), + ])); + + let path_struct_t = DataType::Struct(Fields::from(vec![ + Field::new("layer", DataType::UInt16, false), + Field::new("dtype", DataType::UInt16, false), + Field::new("path_type", DataType::Int16, false), + Field::new("extension_start", DataType::Int32, true), + Field::new("extension_end", DataType::Int32, true), + Field::new("width", DataType::Int32, false), + Field::new("xy", coords_t.clone(), false), + Field::new("properties", property_list_t.clone(), true), + ])); + + let boxnode_struct_t = DataType::Struct(Fields::from(vec![ + Field::new("layer", DataType::UInt16, false), + Field::new("dtype", DataType::UInt16, false), + Field::new("xy", coords_t.clone(), false), + Field::new("properties", property_list_t.clone(), true), + ])); + + + let ref_list_t = DataType::List(Arc::new( + Field::new_list_field(ref_struct_t, false) + )); + + let text_list_t = DataType::List(Arc::new( + Field::new_list_field(text_struct_t, false) + )); + + let boundary_list_t = DataType::List(Arc::new( + Field::new_list_field(boundary_struct_t, false) + )); + + let path_list_t = DataType::List(Arc::new( + Field::new_list_field(path_struct_t, false) + )); + + let boxnode_list_t = DataType::List(Arc::new( + Field::new_list_field(boxnode_struct_t, false) + )); + + + let cell_struct_t = DataType::Struct(Fields::from(vec![ + Field::new("id", DataType::UInt32, false), + Field::new("file_offset", DataType::UInt64, false), + Field::new("refs", ref_list_t, false), + Field::new("boundaries", boundary_list_t, false), + Field::new("paths", path_list_t, false), + Field::new("nodes", boxnode_list_t.clone(), true), + Field::new("boxes", boxnode_list_t.clone(), true), + Field::new("texts", text_list_t, false), + ])); + + let mut lib_builder = StructBuilder::from_fields(vec![ + Field::new("cell_names", DataType::Utf8, false), + Field::new("cells", cell_struct_t, false), + ], + 0, + ); + + let cells_builder = lib_builder.field_builder::(0).unwrap(); + + + let mut names = HashMap::::new(); + + let (mut input, mut header) = RecordHeader::read(input)?; + while header.tag != records::RTAG_ENDLIB { + (input, _) = take_bytes(input, header.data_size)?; + if header.tag == records::RTAG_BGNSTR { + let name_bytes; + (input, name_bytes) = records::STRNAME::read(input)?; + let name = String::from_utf8(name_bytes).unwrap(); + + let next_id = names.len(); + let id = names.entry(name).or_insert(next_id.try_into().unwrap()); + let position = input_size - input.len(); + + let cell_builder = cells_builder.values().as_any_mut().downcast_mut::().unwrap(); + let id_builder = cell_builder.field_builder::(0).unwrap(); + id_builder.append_value(*id); + + let offset_builder = cell_builder.field_builder::(1).unwrap(); + offset_builder.append_value(position.try_into().unwrap()); + + (input, _) = read_elements(input, cell_builder, &mut names)?; + + cells_builder.append(true); + } + (input, header) = RecordHeader::read(input)?; + } + + let mut ids: HashMap = names.into_iter().map(|(kk, vv)| (vv, kk)).collect(); + let names_builder = lib_builder.field_builder::(1).unwrap(); + for id in 0..ids.len() { + names_builder.append_value(ids.remove(&id.try_into().unwrap()).unwrap()); + } + + let lib = lib_builder.finish(); + Ok((input, lib)) +} + + +pub fn read_elements<'a>(input: &'a [u8], cell_builder: &mut StructBuilder, names: &mut HashMap) -> IResult<'a, ()> { + let (mut input, mut header) = RecordHeader::read(input)?; + while header.tag != records::RTAG_ENDSTR { + match header.tag { + records::RTAG_BOUNDARY => {(input, _) = read_boundary(input, cell_builder)?;}, + records::RTAG_PATH => {read_path(input, cell_builder)?;}, + records::RTAG_NODE => {read_boxnode(input, cell_builder, header.tag)?;}, + records::RTAG_BOX => {read_boxnode(input, cell_builder, header.tag)?;}, + records::RTAG_TEXT => {read_text(input, cell_builder)?;}, + records::RTAG_SREF => {read_ref(input, cell_builder, header.tag, names)?;}, + records::RTAG_AREF => {read_ref(input, cell_builder, header.tag, names)?;}, + _ => { + // don't care, skip + (input, _) = take_bytes(input, header.data_size)?; + } + } + (input, header) = RecordHeader::read(input)?; + } + Ok((input, ())) +} + +pub fn read_boundary<'a>(input: &'a [u8], cell_builder: &mut StructBuilder) -> IResult<'a, ()> { + let boundaries_builder = cell_builder.field_builder::(3).unwrap(); + let boundary_builder = boundaries_builder.values().as_any_mut().downcast_mut::().unwrap(); + + let (input, _) = records::BOUNDARY::read(input)?; + + let (input, layer) = LAYER::skip_and_read(input)?; + let layer_builder = boundary_builder.field_builder::(0).unwrap(); + layer_builder.append_value(layer); + + let (input, dtype) = DATATYPE::read(input)?; + let dtype_builder = boundary_builder.field_builder::(1).unwrap(); + dtype_builder.append_value(dtype); + + let xys_builder = boundary_builder.field_builder::(2).unwrap(); + let xy_builder = xys_builder.values().as_any_mut().downcast_mut::().unwrap(); + let (input, xy_iter) = XY::read(input)?; + for xy in xy_iter { + xy_builder.append_value(xy); + } + xys_builder.append(true); + + let props_builder = boundary_builder.field_builder::(3).unwrap(); + let (input, ()) = read_properties(input, props_builder)?; + + boundary_builder.append(true); + boundaries_builder.append(true); + Ok((input, ())) +} + + +pub fn read_path<'a>(input: &'a [u8], cell_builder: &mut StructBuilder) -> IResult<'a, ()> { + let paths_builder = cell_builder.field_builder::(4).unwrap(); + let path_builder = paths_builder.values().as_any_mut().downcast_mut::().unwrap(); + + + let (input, _) = records::PATH::read(input)?; + + let (input, layer) = LAYER::skip_and_read(input)?; + let (input, dtype) = DATATYPE::read(input)?; + let layer_builder = path_builder.field_builder::(0).unwrap(); + layer_builder.append_value(layer); + let dtype_builder = path_builder.field_builder::(1).unwrap(); + dtype_builder.append_value(dtype); + + let mut path_type = None; + let mut width = None; + let mut bgn_ext = None; + let mut end_ext = None; + + let (mut input, mut header) = RecordHeader::read(&input)?; + while header.tag != records::RTAG_XY { + match header.tag { + records::RTAG_PATHTYPE => { + let _path_type; + (input, _path_type) = PATHTYPE::read_data(input, header.data_size)?; + path_type = Some(_path_type); + }, + records::RTAG_WIDTH => { + let _width; + (input, _width) = WIDTH::read_data(input, header.data_size)?; + width = Some(_width); + }, + records::RTAG_BGNEXTN => { + let _bgn_ext; + (input, _bgn_ext) = BGNEXTN::read_data(input, header.data_size)?; + bgn_ext = Some(_bgn_ext); + }, + records::RTAG_ENDEXTN => { + let _end_ext; + (input, _end_ext) = ENDEXTN::read_data(input, header.data_size)?; + end_ext = Some(_end_ext); + }, + _ => + return fail(input, format!("Unexpected tag {:04x}", header.tag)), + }; + (input, header) = RecordHeader::read(&input)?; + } + let path_type_builder = path_builder.field_builder::(2).unwrap(); + path_type_builder.append_option(path_type); + let ext0_builder = path_builder.field_builder::(3).unwrap(); + ext0_builder.append_option(bgn_ext); + let ext1_builder = path_builder.field_builder::(4).unwrap(); + ext1_builder.append_option(end_ext); + let width_builder = path_builder.field_builder::(5).unwrap(); + width_builder.append_option(width); + + let xys_builder = path_builder.field_builder::(6).unwrap(); + let (input, xy_iter) = XY::read(input)?; + for xy in xy_iter { + let xy_builder = xys_builder.values().as_any_mut().downcast_mut::().unwrap(); + xy_builder.append_value(xy); + } + xys_builder.append(true); + + let props_builder = path_builder.field_builder::(7).unwrap(); + let (input, ()) = read_properties(input, props_builder)?; + + path_builder.append(true); + paths_builder.append(true); + Ok((input, ())) +} + +pub fn read_boxnode<'a>(input: &'a [u8], cell_builder: &mut StructBuilder, tag: u16) -> IResult<'a, ()> { + let field_num = match tag { + records::RTAG_NODE => 5, + records::RTAG_BOX => 6, + _ => return fail(input, format!("Unexpected tag {:04x}", tag)), + }; + + let boxnodes_builder = cell_builder.field_builder::(field_num).unwrap(); + let boxnode_builder = boxnodes_builder.values().as_any_mut().downcast_mut::().unwrap(); + + let (input, _) = match tag { + records::RTAG_NODE => records::NODE::read(input)?, + records::RTAG_BOX => records::BOX::read(input)?, + _ => return fail(input, format!("Unexpected tag {:04x}", tag)), + }; + + let layer_builder = boxnode_builder.field_builder::(0).unwrap(); + let (input, layer) = LAYER::skip_and_read(input)?; + layer_builder.append_value(layer); + + let (input, dtype) = match tag { + records::RTAG_NODE => NODETYPE::read(input)?, + records::RTAG_BOX => BOXTYPE::read(input)?, + _ => return fail(input, format!("Unexpected tag {:04x}", tag)), + }; + let dtype_builder = boxnode_builder.field_builder::(1).unwrap(); + dtype_builder.append_value(dtype); + + let xys_builder = boxnode_builder.field_builder::(2).unwrap(); + let xy_builder = xys_builder.values().as_any_mut().downcast_mut::().unwrap(); + let (input, xy_iter) = XY::read(input)?; + for xy in xy_iter { + xy_builder.append_value(xy); + } + xys_builder.append(true); + + let props_builder = boxnode_builder.field_builder::(3).unwrap(); + let (input, ()) = read_properties(input, props_builder)?; + + boxnode_builder.append(true); + boxnodes_builder.append(true); + Ok((input, ())) +} + +pub fn read_text<'a>(input: &'a [u8], cell_builder: &mut StructBuilder) -> IResult<'a, ()> { + let texts_builder = cell_builder.field_builder::(7).unwrap(); + let text_builder = texts_builder.values().as_any_mut().downcast_mut::().unwrap(); + + + let mut path_type = None; + let mut pres_hori = None; + let mut pres_vert = None; + let mut pres_font = None; + let mut invert_y = None; + let mut width = None; + let mut mag = None; + let mut angle_deg = None; + + let (input, layer) = LAYER::skip_and_read(input)?; + let layer_builder = text_builder.field_builder::(0).unwrap(); + layer_builder.append_value(layer); + + let (input, dtype) = TEXTTYPE::read(input)?; + let dtype_builder = text_builder.field_builder::(1).unwrap(); + dtype_builder.append_value(dtype); + + let (mut input, mut header) = RecordHeader::read(input)?; + while header.tag != records::RTAG_XY { + match header.tag { + // TODO warn if repeat tags? + records::RTAG_PRESENTATION => { + let _presentation; + (input, _presentation) = PRESENTATION::read_data(input, header.data_size)?; + pres_hori = Some(_presentation[14] as u8 * 2 + _presentation[15] as u8); + pres_vert = Some(_presentation[12] as u8 * 2 + _presentation[13] as u8); + pres_font = Some(_presentation[10] as u8 * 2 + _presentation[11] as u8); + }, + records::RTAG_PATHTYPE => { + let _path_type; + (input, _path_type) = PATHTYPE::read_data(input, header.data_size)?; + path_type = Some(_path_type); + }, + records::RTAG_WIDTH => { + let _width; + (input, _width) = WIDTH::read_data(input, header.data_size)?; + width = Some(_width); + }, + records::RTAG_STRANS => { + let strans; + (input, strans) = STRANS::read_data(input, header.data_size)?; + invert_y = Some(strans[0]); + }, + records::RTAG_MAG => { + let _mag; + (input, _mag) = MAG::read_data(input, header.data_size)?; + mag = Some(_mag); + }, + records::RTAG_ANGLE => { + let _angle_deg; + (input, _angle_deg) = ANGLE::read_data(input, header.data_size)?; + angle_deg = Some(_angle_deg); + }, + _ => + return fail(input, format!("Unexpected tag {:04x}", header.tag)), + } + (input, header) = RecordHeader::read(input)?; + } + + let pres_hori_builder = text_builder.field_builder::(2).unwrap(); + pres_hori_builder.append_option(pres_hori); + let pres_vert_builder = text_builder.field_builder::(3).unwrap(); + pres_vert_builder.append_option(pres_vert); + let pres_font_builder = text_builder.field_builder::(4).unwrap(); + pres_font_builder.append_option(pres_font); + let path_type_builder = text_builder.field_builder::(5).unwrap(); + path_type_builder.append_option(path_type); + let width_builder = text_builder.field_builder::(6).unwrap(); + width_builder.append_option(width); + let inv_builder = text_builder.field_builder::(7).unwrap(); + inv_builder.append_option(invert_y); + let mag_builder = text_builder.field_builder::(8).unwrap(); + mag_builder.append_option(mag); + let angle_builder = text_builder.field_builder::(9).unwrap(); + angle_builder.append_option(angle_deg); + + let (input, mut xy_iter) = XY::read(input)?; + let x_builder = text_builder.field_builder::(10).unwrap(); + x_builder.append_value(xy_iter.next().unwrap()); + let y_builder = text_builder.field_builder::(11).unwrap(); + y_builder.append_value(xy_iter.next().unwrap()); + + let (input, string_bytes) = STRING::read(input)?; + let string = String::from_utf8(string_bytes).unwrap(); + let string_builder = text_builder.field_builder::(12).unwrap(); + string_builder.append_value(string); + + let props_builder = text_builder.field_builder::(13).unwrap(); + let (input, ()) = read_properties(input, props_builder)?; + + text_builder.append(true); + texts_builder.append(true); + Ok((input, ())) +} + + + +pub fn read_ref<'a>(input: &'a [u8], cell_builder: &mut StructBuilder, tag: u16, names: &mut HashMap) -> IResult<'a, ()> { + let is_aref = tag == records::RTAG_AREF; + let refs_builder = cell_builder.field_builder::(7).unwrap(); + let ref_builder = refs_builder.values().as_any_mut().downcast_mut::().unwrap(); + + let mut invert_y = None; + let mut mag = None; + let mut angle_deg = None; + let mut colrow = None; + + let (input, struct_name_bytes) = SNAME::skip_and_read(input)?; + let struct_name = String::from_utf8(struct_name_bytes).unwrap(); + let next_id = names.len(); + let id = names.entry(struct_name).or_insert(next_id.try_into().unwrap()); + let target_builder = ref_builder.field_builder::(0).unwrap(); + target_builder.append_value(*id); + + let (mut input, mut header) = RecordHeader::read(input)?; + while header.tag != records::RTAG_XY { + match header.tag { + records::RTAG_STRANS => { + let strans; + (input, strans) = STRANS::read_data(input, header.data_size)?; + invert_y = Some(strans[0]); + }, + records::RTAG_MAG => { + let _mag; + (input, _mag) = MAG::read_data(input, header.data_size)?; + mag = Some(_mag); + }, + records::RTAG_ANGLE => { + let _angle_deg; + (input, _angle_deg) = ANGLE::read_data(input, header.data_size)?; + angle_deg = Some(_angle_deg); + }, + records::RTAG_COLROW => { + let mut _colrow; + (input, _colrow) = COLROW::read_data(input, header.data_size)?; + colrow = Some((_colrow.next().unwrap(), _colrow.next().unwrap())); + if !is_aref { + return fail(input, "Got a COLROW record inside an SREF".to_string()); + } + }, + _ => + return fail(input, format!("Unexpected tag {:04x}", header.tag)), + }; + (input, header) = RecordHeader::read(input)?; + } + let inv_builder = ref_builder.field_builder::(1).unwrap(); + inv_builder.append_option(invert_y); + let mag_builder = ref_builder.field_builder::(2).unwrap(); + mag_builder.append_option(mag); + let angle_builder = ref_builder.field_builder::(3).unwrap(); + angle_builder.append_option(angle_deg); + + + let (input, mut xy_iter) = XY::read_data(input, header.data_size)?; + let x_builder = ref_builder.field_builder::(4).unwrap(); + x_builder.append_value(xy_iter.next().unwrap()); + let y_builder = ref_builder.field_builder::(5).unwrap(); + y_builder.append_value(xy_iter.next().unwrap()); + + let rep_builder = ref_builder.field_builder::(6).unwrap(); + if is_aref { + let x0_builder = rep_builder.field_builder::(0).unwrap(); + x0_builder.append_value(xy_iter.next().unwrap()); + let y0_builder = rep_builder.field_builder::(1).unwrap(); + y0_builder.append_value(xy_iter.next().unwrap()); + let x1_builder = rep_builder.field_builder::(2).unwrap(); + x1_builder.append_value(xy_iter.next().unwrap()); + let y1_builder = rep_builder.field_builder::(3).unwrap(); + y1_builder.append_value(xy_iter.next().unwrap()); + + match colrow { + None => return fail(input, "AREF without COLROW before XY".to_string()), + Some((count0, count1)) => { + let count0_builder = rep_builder.field_builder::(4).unwrap(); + count0_builder.append_value(count0); + let count1_builder = rep_builder.field_builder::(5).unwrap(); + count1_builder.append_value(count1); + }, + } + } + rep_builder.append(is_aref); + + let props_builder = ref_builder.field_builder::(7).unwrap(); + let (input, ()) = read_properties(input, props_builder)?; + + ref_builder.append(true); + refs_builder.append(true); + Ok((input, ())) +} /// @@ -30,26 +571,35 @@ use std::io::Write; /// Returns: /// propattr: -> propvalue mapping /// -pub fn read_properties(input: &[u8]) -> IResult>> { - let mut properties = HashMap::new(); +pub fn read_properties<'a>(input: &'a [u8], props_builder: &mut DListBuilder) -> IResult<'a, ()> { + let prop_builder = props_builder.values().as_any_mut().downcast_mut::().unwrap(); let (mut input, mut header) = RecordHeader::read(input)?; while header.tag != ENDEL::tag() { if header.tag == PROPATTR::tag() { - let result = PROPATTR::read_data(input, header.data_size)?; - input = result.0; - let key = result.1; - let result = PROPVALUE::read(input)?; - input = result.0; - let value = result.1; - assert!(!properties.contains_key(&key), "Duplicate property key: {}", key); - properties.insert(key, value); + let key; + let value_bytes; + (input, key) = PROPATTR::read_data(input, header.data_size)?; + (input, value_bytes) = PROPVALUE::read(input)?; + + let value = String::from_utf8(value_bytes).unwrap(); + //assert!(!properties.contains_key(&key), "Duplicate property key: {}", key); + + let key_builder = prop_builder.field_builder::(0).unwrap(); + key_builder.append_value(key); + + let val_builder = prop_builder.field_builder::(1).unwrap(); + val_builder.append_value(value); + + prop_builder.append(true); } (input, header) = RecordHeader::read(input)?; } - Ok((input, properties)) + props_builder.append(true); + Ok((input, ())) } +/* /// /// Write element properties. @@ -530,3 +1080,4 @@ impl Element for Text { Ok(size) } } +*/ diff --git a/src/library.rs b/src/library.rs index e5b5758..ee392ed 100644 --- a/src/library.rs +++ b/src/library.rs @@ -3,13 +3,13 @@ /// use std::io::Write; -use std::collections::HashMap; +//use std::collections::HashMap; pub use crate::record; pub use crate::record::{RecordHeader, Record}; pub use crate::records; pub use crate::elements; -pub use crate::elements::{Element}; +//pub use crate::elements::{Element}; pub use crate::basic::{IResult, OResult, take_bytes, fail}; @@ -90,7 +90,7 @@ impl FileHeader { } } - +/* /// /// Scan through a GDS file, building a table of /// {b'structure_name': byte_offset}. @@ -122,8 +122,9 @@ pub fn scan_structs(input: &[u8]) -> IResult, usize>> { } Ok((input, positions)) } +*/ - +/* #[derive(Debug, Clone)] pub struct Cell { name: Vec, @@ -287,7 +288,7 @@ impl Cell { Ok(size) } } - +*/ /* /// diff --git a/src/record.rs b/src/record.rs index 41921c4..da2e12b 100644 --- a/src/record.rs +++ b/src/record.rs @@ -8,7 +8,7 @@ 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}; +use crate::basic::{OResult, IResult, fail, parse_u16, take_bytes}; //ErrType, use crate::records; @@ -23,7 +23,7 @@ pub struct RecordHeader { } impl RecordHeader { - pub fn read(input: &[u8]) -> IResult { + pub fn read<'a>(input: &[u8]) -> IResult { let (input, size) = parse_u16(input)?; let (input, tag) = parse_u16(input)?; Ok((input, RecordHeader{tag:tag, data_size:size - 4})) @@ -45,13 +45,13 @@ impl RecordHeader { pub trait RecordData { - type BareData; + type BareData<'a>; type InData : ?Sized; type ByteData : AsRef<[u8]>; - fn read(input: &[u8], size: u16) -> IResult; + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>>; fn pack_into(buf: &mut [u8], data: &Self::InData); - //fn size(data: &Self::BareData) -> u16; + //fn size(data: &Self::BareData<'_>) -> u16; fn pack(data: &Self::InData) -> Self::ByteData; } @@ -79,7 +79,7 @@ pub trait Record { RecordHeader{tag: Self::tag(), data_size: data_size}.write(ww) } - fn read_data(input: &[u8], size: u16) -> IResult { + fn read_data(input: &[u8], size: u16) -> IResult> { RData::read(input, size) } @@ -108,7 +108,7 @@ pub trait Record { Ok((input, true)) } - fn skip_and_read(input: &[u8]) -> IResult { + 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)?; @@ -127,7 +127,7 @@ pub trait Record { } } - fn read(input: &[u8]) -> IResult { + fn read<'a>(input: &'a [u8]) -> IResult<'a, RData::BareData<'a>> { let (input, size) = Self::expect_header(input)?; Self::check_size(size).unwrap(); let (input, data) = Self::read_data(input, size)?; @@ -147,11 +147,11 @@ pub trait Record { pub struct BitArray; impl RecordData for BitArray { - type BareData = [bool; 16]; + type BareData<'a> = [bool; 16]; type InData = [bool; 16]; type ByteData = [u8; 2]; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size == 2); parse_bitarray(input) } @@ -170,11 +170,11 @@ impl RecordData for BitArray { pub struct Int2; impl RecordData for Int2 { - type BareData = i16; + type BareData<'a> = i16; type InData = i16; type ByteData = [u8; 2]; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size == 2); parse_int2(input) } @@ -192,11 +192,11 @@ impl RecordData for Int2 { pub struct Int4; impl RecordData for Int4 { - type BareData = i32; + type BareData<'a> = i32; type InData = i32; type ByteData = [u8; 4]; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size == 4); parse_int4(input) } @@ -215,18 +215,15 @@ impl RecordData for Int4 { pub struct Int2Array; impl RecordData for Int2Array { - type BareData = Vec; + type BareData<'a> = Int2ArrayReader<'a>; type InData = [i16]; type ByteData = Vec; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size % 2 == 0, "Record must contain an integer quantity of integers"); - let mut buf = Vec::with_capacity(size as usize / 2); - let mut input = input; - for ii in 0..buf.len() { - (input, buf[ii]) = parse_int2(input)?; - } - Ok((input, buf)) + //let mut input = input; + let (input, bytes) = take_bytes(input, size)?; + Ok((input, Int2ArrayReader{bytes: bytes})) } fn pack_into(buf: &mut [u8], data: &Self::InData) { @@ -240,20 +237,34 @@ impl RecordData for Int2Array { } } +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 = Vec; + type BareData<'a> = Int4ArrayReader<'a>; type InData = [i32]; type ByteData = Vec; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size % 4 == 0, "Record must contain an integer quantity of integers"); - let mut buf = Vec::with_capacity(size as usize / 4); - let mut input = input; - for ii in 0..buf.len() { - (input, buf[ii]) = parse_int4(input)?; - } - Ok((input, buf)) + //let mut input = input; + let (input, bytes) = take_bytes(input, size)?; + Ok((input, Int4ArrayReader{bytes: bytes})) } fn pack_into(buf: &mut [u8], data: &Self::InData) { @@ -267,13 +278,30 @@ impl RecordData for Int4Array { } } +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 = f64; + type BareData<'a> = f64; type InData = f64; type ByteData = [u8; 8]; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size == 8); parse_real8(input) } @@ -291,11 +319,11 @@ impl RecordData for Real8 { pub struct Real8Pair; impl RecordData for Real8Pair { - type BareData = (f64, f64); + type BareData<'a> = (f64, f64); type InData = (f64, f64); type ByteData = [u8; 2 * 8]; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size == 2 * 8); let (input, data0) = parse_real8(input)?; let (input, data1) = parse_real8(input)?; @@ -321,11 +349,11 @@ impl RecordData for Real8Pair { pub struct ASCII; impl RecordData for ASCII { - type BareData = Vec; + type BareData<'a> = Vec; type InData = [u8]; type ByteData = Vec; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { parse_ascii(input, size) } @@ -343,11 +371,11 @@ impl RecordData for ASCII { pub struct DateTimePair; impl RecordData for DateTimePair { - type BareData = [[i16; 6]; 2]; + type BareData<'a> = [[i16; 6]; 2]; type InData = [[i16; 6]; 2]; type ByteData = [u8; 2 * 6 * 2]; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size == 2 * 6 * 2); let (input, data0) = parse_datetime(input)?; let (input, data1) = parse_datetime(input)?; @@ -373,11 +401,11 @@ impl RecordData for DateTimePair { pub struct Empty; impl RecordData for Empty { - type BareData = (); + type BareData<'a> = (); type InData = (); type ByteData = [u8; 0]; - fn read(input: &[u8], size: u16) -> IResult { + fn read<'a>(input: &'a [u8], size: u16) -> IResult<'a, Self::BareData<'a>> { assert!(size == 0); Ok((input, ())) }