performance work

This commit is contained in:
Jan Petykiewicz 2026-04-02 20:22:15 -07:00
commit 22040d9432
2 changed files with 591 additions and 96 deletions

View file

@ -28,6 +28,68 @@ use arrow::array::{
pub type DListBuilder = ListBuilder<Box<dyn ArrayBuilder>>;
pub type FListBuilder = FixedSizeListBuilder<Box<dyn ArrayBuilder>>;
struct PropertyRecord {
key: i16,
value: String,
}
struct BoundaryRecord {
layer_id: u32,
vertices: Vec<i32>,
properties: Vec<PropertyRecord>,
}
struct BoundaryBatchRecord {
layer_id: u32,
vertices: Vec<i32>,
vertex_offsets: Vec<u32>,
}
struct RectBatchRecord {
layer_id: u32,
rects: Vec<i32>,
}
struct SRefRecord {
target_id: u32,
invert_y: bool,
scale: f64,
angle_rad: f64,
xy: u64,
properties: Vec<PropertyRecord>,
}
struct ARefRecord {
target_id: u32,
invert_y: bool,
scale: f64,
angle_rad: f64,
xy: u64,
xy0: u64,
xy1: u64,
counts: u32,
properties: Vec<PropertyRecord>,
}
enum RefRecord {
SRef(SRefRecord),
ARef(ARefRecord),
}
const UNIT_COUNTS: u32 = (1_u32 << 16) | 1_u32;
fn layer_id_for(
layer: i16,
dtype: i16,
layers: &mut HashMap<u32, u32>,
) -> u32 {
let layer32 = ((layer as u16 as u32) << 16) | (dtype as u16 as u32);
let next_id = layers.len();
*layers.entry(layer32).or_insert(next_id.try_into().unwrap())
}
fn insert_layer(
layer: i16,
@ -36,11 +98,9 @@ fn insert_layer(
struct_builder: &mut StructBuilder,
field_index: usize,
) {
let layer32 = ((layer as u16 as u32) << 16) | (dtype as u16 as u32);
let next_id = layers.len();
let id = layers.entry(layer32).or_insert(next_id.try_into().unwrap());
let id = layer_id_for(layer, dtype, layers);
let layer_builder = struct_builder.field_builder::<UInt32Builder>(field_index).unwrap();
layer_builder.append_value(*id);
layer_builder.append_value(id);
}
@ -51,12 +111,25 @@ pub fn read_elements<'a>(
layers: &mut HashMap<u32, u32>,
) -> IResult<'a, ()> {
let mut input = input;
let mut boundaries = Vec::<BoundaryRecord>::new();
let mut srefs = Vec::<SRefRecord>::new();
let mut arefs = Vec::<ARefRecord>::new();
let (_, mut header) = RecordHeader::read(input)?; // don't consume tag
while header.tag != records::RTAG_ENDSTR {
(input, _) = match header.tag {
records::RTAG_SREF => read_ref(input, cell_builder, header.tag, names)?,
records::RTAG_AREF => read_ref(input, cell_builder, header.tag, names)?,
records::RTAG_BOUNDARY => read_boundary(input, cell_builder, layers)?,
records::RTAG_SREF | records::RTAG_AREF => {
let (next_input, ref_record) = read_ref(input, header.tag, names)?;
match ref_record {
RefRecord::SRef(sref) => srefs.push(sref),
RefRecord::ARef(aref) => arefs.push(aref),
}
(next_input, ())
},
records::RTAG_BOUNDARY => {
let (next_input, boundary) = read_boundary(input, layers)?;
boundaries.push(boundary);
(next_input, ())
},
records::RTAG_PATH => read_path(input, cell_builder, layers)?,
records::RTAG_NODE => read_boxnode(input, cell_builder, header.tag, layers)?,
records::RTAG_BOX => read_boxnode(input, cell_builder, header.tag, layers)?,
@ -71,50 +144,363 @@ pub fn read_elements<'a>(
}
(input, _) = take_bytes(input, 4_usize)?; // consume endstr tag
let refs_builder = cell_builder.field_builder::<DListBuilder>(2).unwrap();
refs_builder.append(true);
let boundaries_builder = cell_builder.field_builder::<DListBuilder>(3).unwrap();
boundaries_builder.append(true);
let paths_builder = cell_builder.field_builder::<DListBuilder>(4).unwrap();
let mut sref_plain = Vec::<SRefRecord>::with_capacity(srefs.len() + arefs.len() / 4);
let mut sref_props = Vec::<SRefRecord>::with_capacity(srefs.len() / 16 + arefs.len() / 64);
for sref in srefs {
if sref.properties.is_empty() {
sref_plain.push(sref);
} else {
sref_props.push(sref);
}
}
let mut aref_plain = Vec::<ARefRecord>::with_capacity(arefs.len());
let mut aref_props = Vec::<ARefRecord>::with_capacity(arefs.len() / 16);
for aref in arefs {
if aref.counts == UNIT_COUNTS {
let sref = aref_to_sref(aref);
if sref.properties.is_empty() {
sref_plain.push(sref);
} else {
sref_props.push(sref);
}
} else if aref.properties.is_empty() {
aref_plain.push(aref);
} else {
aref_props.push(aref);
}
}
sref_plain.sort_by_key(|sref| sref.target_id);
aref_plain.sort_by_key(|aref| aref.target_id);
let mut boundary_plain = Vec::<BoundaryRecord>::with_capacity(boundaries.len());
let mut boundary_props = Vec::<BoundaryRecord>::with_capacity(boundaries.len() / 16);
for boundary in boundaries {
if boundary.properties.is_empty() {
boundary_plain.push(boundary);
} else {
boundary_props.push(boundary);
}
}
boundary_plain.sort_by_key(|boundary| boundary.layer_id);
let mut rect_batches = Vec::<RectBatchRecord>::new();
let mut boundary_batches = Vec::<BoundaryBatchRecord>::new();
let mut ii = 0;
while ii < boundary_plain.len() {
let start = ii;
let layer_id = boundary_plain[ii].layer_id;
while ii < boundary_plain.len() && boundary_plain[ii].layer_id == layer_id {
ii += 1;
}
let group = &boundary_plain[start..ii];
let rect_capacity = group.len() * 4;
let vertex_capacity = group.iter().map(|boundary| boundary.vertices.len()).sum();
let mut rect_batch = RectBatchRecord {
layer_id,
rects: Vec::with_capacity(rect_capacity),
};
let mut boundary_batch = BoundaryBatchRecord {
layer_id,
vertices: Vec::with_capacity(vertex_capacity),
vertex_offsets: Vec::with_capacity(group.len()),
};
let mut next_offset: u32 = 0;
for boundary in group {
if let Some(rect) = boundary_to_rect(&boundary.vertices) {
rect_batch.rects.extend_from_slice(&rect);
} else {
boundary_batch.vertex_offsets.push(next_offset);
boundary_batch.vertices.extend_from_slice(&boundary.vertices);
next_offset += (boundary.vertices.len() / 2) as u32;
}
}
if !rect_batch.rects.is_empty() {
rect_batches.push(rect_batch);
}
if !boundary_batch.vertex_offsets.is_empty() {
boundary_batches.push(boundary_batch);
}
}
let sref_builder = cell_builder.field_builder::<DListBuilder>(2).unwrap();
for sref in sref_plain {
append_sref(sref_builder, sref);
}
sref_builder.append(true);
let aref_builder = cell_builder.field_builder::<DListBuilder>(3).unwrap();
for aref in aref_plain {
append_aref(aref_builder, aref);
}
aref_builder.append(true);
let sref_props_builder = cell_builder.field_builder::<DListBuilder>(4).unwrap();
for sref in sref_props {
append_sref_prop(sref_props_builder, sref);
}
sref_props_builder.append(true);
let aref_props_builder = cell_builder.field_builder::<DListBuilder>(5).unwrap();
for aref in aref_props {
append_aref_prop(aref_props_builder, aref);
}
aref_props_builder.append(true);
let rect_batches_builder = cell_builder.field_builder::<DListBuilder>(6).unwrap();
for rect_batch in rect_batches {
append_rect_batch(rect_batches_builder, rect_batch);
}
rect_batches_builder.append(true);
let boundary_batches_builder = cell_builder.field_builder::<DListBuilder>(7).unwrap();
for boundary_batch in boundary_batches {
append_boundary_batch(boundary_batches_builder, boundary_batch);
}
boundary_batches_builder.append(true);
let boundary_props_builder = cell_builder.field_builder::<DListBuilder>(8).unwrap();
for boundary in boundary_props {
append_boundary_prop(boundary_props_builder, boundary);
}
boundary_props_builder.append(true);
let paths_builder = cell_builder.field_builder::<DListBuilder>(9).unwrap();
paths_builder.append(true);
let nodes_builder = cell_builder.field_builder::<DListBuilder>(5).unwrap();
let nodes_builder = cell_builder.field_builder::<DListBuilder>(10).unwrap();
nodes_builder.append(true);
let boxes_builder = cell_builder.field_builder::<DListBuilder>(6).unwrap();
let boxes_builder = cell_builder.field_builder::<DListBuilder>(11).unwrap();
boxes_builder.append(true);
let texts_builder = cell_builder.field_builder::<DListBuilder>(7).unwrap();
let texts_builder = cell_builder.field_builder::<DListBuilder>(12).unwrap();
texts_builder.append(true);
Ok((input, ()))
}
pub fn read_boundary<'a>(
input: &'a [u8],
cell_builder: &mut StructBuilder,
layers: &mut HashMap<u32, u32>,
) -> IResult<'a, ()> {
let boundaries_builder = cell_builder.field_builder::<DListBuilder>(3).unwrap();
let boundary_builder = boundaries_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
fn append_sref(
sref_builder: &mut DListBuilder,
sref: SRefRecord,
) {
let sref_struct_builder = sref_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let target_builder = sref_struct_builder.field_builder::<UInt32Builder>(0).unwrap();
target_builder.append_value(sref.target_id);
let invert_builder = sref_struct_builder.field_builder::<BooleanBuilder>(1).unwrap();
invert_builder.append_value(sref.invert_y);
let scale_builder = sref_struct_builder.field_builder::<Float64Builder>(2).unwrap();
scale_builder.append_value(sref.scale);
let angle_builder = sref_struct_builder.field_builder::<Float64Builder>(3).unwrap();
angle_builder.append_value(sref.angle_rad);
let xy_builder = sref_struct_builder.field_builder::<UInt64Builder>(4).unwrap();
xy_builder.append_value(sref.xy);
sref_struct_builder.append(true);
}
fn append_aref(
aref_builder: &mut DListBuilder,
aref: ARefRecord,
) {
let aref_struct_builder = aref_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let target_builder = aref_struct_builder.field_builder::<UInt32Builder>(0).unwrap();
target_builder.append_value(aref.target_id);
let invert_builder = aref_struct_builder.field_builder::<BooleanBuilder>(1).unwrap();
invert_builder.append_value(aref.invert_y);
let scale_builder = aref_struct_builder.field_builder::<Float64Builder>(2).unwrap();
scale_builder.append_value(aref.scale);
let angle_builder = aref_struct_builder.field_builder::<Float64Builder>(3).unwrap();
angle_builder.append_value(aref.angle_rad);
let xy_builder = aref_struct_builder.field_builder::<UInt64Builder>(4).unwrap();
xy_builder.append_value(aref.xy);
let xy0_builder = aref_struct_builder.field_builder::<UInt64Builder>(5).unwrap();
xy0_builder.append_value(aref.xy0);
let xy1_builder = aref_struct_builder.field_builder::<UInt64Builder>(6).unwrap();
xy1_builder.append_value(aref.xy1);
let counts_builder = aref_struct_builder.field_builder::<UInt32Builder>(7).unwrap();
counts_builder.append_value(aref.counts);
aref_struct_builder.append(true);
}
fn append_properties(
props_builder: &mut DListBuilder,
properties: Vec<PropertyRecord>,
) {
for prop in properties {
let prop_builder = props_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let key_builder = prop_builder.field_builder::<Int16Builder>(0).unwrap();
key_builder.append_value(prop.key);
let val_builder = prop_builder.field_builder::<StringBuilder>(1).unwrap();
val_builder.append_value(prop.value);
prop_builder.append(true);
}
props_builder.append(true);
}
fn append_sref_prop(
sref_props_builder: &mut DListBuilder,
sref: SRefRecord,
) {
let sref_prop_builder = sref_props_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let target_builder = sref_prop_builder.field_builder::<UInt32Builder>(0).unwrap();
target_builder.append_value(sref.target_id);
let invert_builder = sref_prop_builder.field_builder::<BooleanBuilder>(1).unwrap();
invert_builder.append_value(sref.invert_y);
let scale_builder = sref_prop_builder.field_builder::<Float64Builder>(2).unwrap();
scale_builder.append_value(sref.scale);
let angle_builder = sref_prop_builder.field_builder::<Float64Builder>(3).unwrap();
angle_builder.append_value(sref.angle_rad);
let xy_builder = sref_prop_builder.field_builder::<UInt64Builder>(4).unwrap();
xy_builder.append_value(sref.xy);
let props_builder = sref_prop_builder.field_builder::<DListBuilder>(5).unwrap();
append_properties(props_builder, sref.properties);
sref_prop_builder.append(true);
}
fn append_aref_prop(
aref_props_builder: &mut DListBuilder,
aref: ARefRecord,
) {
let aref_prop_builder = aref_props_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let target_builder = aref_prop_builder.field_builder::<UInt32Builder>(0).unwrap();
target_builder.append_value(aref.target_id);
let invert_builder = aref_prop_builder.field_builder::<BooleanBuilder>(1).unwrap();
invert_builder.append_value(aref.invert_y);
let scale_builder = aref_prop_builder.field_builder::<Float64Builder>(2).unwrap();
scale_builder.append_value(aref.scale);
let angle_builder = aref_prop_builder.field_builder::<Float64Builder>(3).unwrap();
angle_builder.append_value(aref.angle_rad);
let xy_builder = aref_prop_builder.field_builder::<UInt64Builder>(4).unwrap();
xy_builder.append_value(aref.xy);
let xy0_builder = aref_prop_builder.field_builder::<UInt64Builder>(5).unwrap();
xy0_builder.append_value(aref.xy0);
let xy1_builder = aref_prop_builder.field_builder::<UInt64Builder>(6).unwrap();
xy1_builder.append_value(aref.xy1);
let counts_builder = aref_prop_builder.field_builder::<UInt32Builder>(7).unwrap();
counts_builder.append_value(aref.counts);
let props_builder = aref_prop_builder.field_builder::<DListBuilder>(8).unwrap();
append_properties(props_builder, aref.properties);
aref_prop_builder.append(true);
}
fn aref_to_sref(aref: ARefRecord) -> SRefRecord {
SRefRecord {
target_id: aref.target_id,
invert_y: aref.invert_y,
scale: aref.scale,
angle_rad: aref.angle_rad,
xy: aref.xy,
properties: aref.properties,
}
}
fn read_boundary<'a>(
input: &'a [u8],
layers: &mut HashMap<u32, u32>,
) -> IResult<'a, BoundaryRecord> {
let (input, _) = records::BOUNDARY::read(input)?;
let (input, layer) = LAYER::skip_and_read(input)?;
let (input, dtype) = DATATYPE::read(input)?;
insert_layer(layer, dtype, layers, boundary_builder, 0);
let layer_id = layer_id_for(layer, dtype, layers);
let xys_builder = boundary_builder.field_builder::<DListBuilder>(1).unwrap();
let xy_builder = xys_builder.values().as_any_mut().downcast_mut::<Int32Builder>().unwrap();
let (input, xy_iter) = XY::read(input)?;
for xy in xy_iter {
xy_builder.append_value(xy);
let mut vertices: Vec<i32> = xy_iter.collect();
vertices.truncate(vertices.len().saturating_sub(2));
let (input, properties) = read_properties_vec(input)?;
Ok((input, BoundaryRecord { layer_id, vertices, properties }))
}
fn append_boundary_batch(
boundary_batches_builder: &mut DListBuilder,
boundary_batch: BoundaryBatchRecord,
) {
let boundary_batch_builder = boundary_batches_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let layer_builder = boundary_batch_builder.field_builder::<UInt32Builder>(0).unwrap();
layer_builder.append_value(boundary_batch.layer_id);
let vertices_builder = boundary_batch_builder.field_builder::<DListBuilder>(1).unwrap();
let vertex_builder = vertices_builder.values().as_any_mut().downcast_mut::<Int32Builder>().unwrap();
vertex_builder.append_slice(&boundary_batch.vertices);
vertices_builder.append(true);
let offsets_builder = boundary_batch_builder.field_builder::<DListBuilder>(2).unwrap();
let offset_builder = offsets_builder.values().as_any_mut().downcast_mut::<UInt32Builder>().unwrap();
offset_builder.append_slice(&boundary_batch.vertex_offsets);
offsets_builder.append(true);
boundary_batch_builder.append(true);
}
fn append_rect_batch(
rect_batches_builder: &mut DListBuilder,
rect_batch: RectBatchRecord,
) {
let rect_batch_builder = rect_batches_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let layer_builder = rect_batch_builder.field_builder::<UInt32Builder>(0).unwrap();
layer_builder.append_value(rect_batch.layer_id);
let rects_builder = rect_batch_builder.field_builder::<DListBuilder>(1).unwrap();
let rect_builder = rects_builder.values().as_any_mut().downcast_mut::<Int32Builder>().unwrap();
rect_builder.append_slice(&rect_batch.rects);
rects_builder.append(true);
rect_batch_builder.append(true);
}
fn append_boundary_prop(
boundary_props_builder: &mut DListBuilder,
boundary: BoundaryRecord,
) {
let boundary_prop_builder = boundary_props_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let layer_builder = boundary_prop_builder.field_builder::<UInt32Builder>(0).unwrap();
layer_builder.append_value(boundary.layer_id);
let vertices_builder = boundary_prop_builder.field_builder::<DListBuilder>(1).unwrap();
let vertex_builder = vertices_builder.values().as_any_mut().downcast_mut::<Int32Builder>().unwrap();
vertex_builder.append_slice(&boundary.vertices);
vertices_builder.append(true);
let props_builder = boundary_prop_builder.field_builder::<DListBuilder>(2).unwrap();
for prop in boundary.properties {
let prop_builder = props_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let key_builder = prop_builder.field_builder::<Int16Builder>(0).unwrap();
key_builder.append_value(prop.key);
let val_builder = prop_builder.field_builder::<StringBuilder>(1).unwrap();
val_builder.append_value(prop.value);
prop_builder.append(true);
}
xys_builder.append(true);
props_builder.append(true);
let props_builder = boundary_builder.field_builder::<DListBuilder>(2).unwrap();
let (input, ()) = read_properties(input, props_builder)?;
boundary_builder.append(true);
Ok((input, ()))
boundary_prop_builder.append(true);
}
@ -123,7 +509,7 @@ pub fn read_path<'a>(
cell_builder: &mut StructBuilder,
layers: &mut HashMap<u32, u32>,
) -> IResult<'a, ()> {
let paths_builder = cell_builder.field_builder::<DListBuilder>(4).unwrap();
let paths_builder = cell_builder.field_builder::<DListBuilder>(9).unwrap();
let path_builder = paths_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let (input, _) = records::PATH::read(input)?;
@ -196,8 +582,8 @@ pub fn read_boxnode<'a>(
layers: &mut HashMap<u32, u32>,
) -> IResult<'a, ()> {
let field_num = match tag {
records::RTAG_NODE => 5,
records::RTAG_BOX => 6,
records::RTAG_NODE => 10,
records::RTAG_BOX => 11,
_ => return fail(input, format!("Unexpected tag {:04x}", tag)),
};
@ -238,7 +624,7 @@ pub fn read_text<'a>(
cell_builder: &mut StructBuilder,
layers: &mut HashMap<u32, u32>,
) -> IResult<'a, ()> {
let texts_builder = cell_builder.field_builder::<DListBuilder>(7).unwrap();
let texts_builder = cell_builder.field_builder::<DListBuilder>(12).unwrap();
let text_builder = texts_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let mut path_type = None;
@ -333,13 +719,53 @@ pub fn read_text<'a>(
}
fn boundary_to_rect(vertices: &[i32]) -> Option<[i32; 4]> {
if vertices.len() != 8 {
return None;
}
pub fn read_ref<'a>(
let xs = [vertices[0], vertices[2], vertices[4], vertices[6]];
let ys = [vertices[1], vertices[3], vertices[5], vertices[7]];
let min_x = *xs.iter().min().unwrap();
let max_x = *xs.iter().max().unwrap();
let min_y = *ys.iter().min().unwrap();
let max_y = *ys.iter().max().unwrap();
if min_x >= max_x || min_y >= max_y {
return None;
}
let mut seen_corners: u8 = 0;
for ii in 0..4 {
let jj = (ii + 1) % 4;
let dx = xs[jj] - xs[ii];
let dy = ys[jj] - ys[ii];
if (dx == 0) == (dy == 0) {
return None;
}
let x = xs[ii];
let y = ys[ii];
if (x != min_x && x != max_x) || (y != min_y && y != max_y) {
return None;
}
let code = ((x == max_x) as u8) << 1 | ((y == max_y) as u8);
seen_corners |= 1 << code;
}
if seen_corners != 0b1111 {
return None;
}
Some([min_x, min_y, max_x, max_y])
}
fn read_ref<'a>(
input: &'a [u8],
cell_builder: &mut StructBuilder,
tag: u16,
names: &mut HashMap<String, u32>,
) -> IResult<'a, ()> {
) -> IResult<'a, RefRecord> {
let (input, _) = match tag {
records::RTAG_SREF => records::SREF::read(input)?,
records::RTAG_AREF => records::AREF::read(input)?,
@ -347,20 +773,15 @@ pub fn read_ref<'a>(
};
let is_aref = tag == records::RTAG_AREF;
let refs_builder = cell_builder.field_builder::<DListBuilder>(2).unwrap();
let ref_builder = refs_builder.values().as_any_mut().downcast_mut::<StructBuilder>().unwrap();
let mut invert_y = None;
let mut mag = None;
let mut angle_deg = None;
let mut invert_y = false;
let mut scale = 1.0;
let mut angle_rad = 0.0;
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::<UInt32Builder>(0).unwrap();
target_builder.append_value(*id);
let (mut input, mut header) = RecordHeader::read(input)?;
while header.tag != records::RTAG_XY {
@ -368,17 +789,17 @@ pub fn read_ref<'a>(
records::RTAG_STRANS => {
let strans;
(input, strans) = STRANS::read_data(input, header.data_size)?;
invert_y = Some(strans[0]);
invert_y = strans[0];
},
records::RTAG_MAG => {
let _mag;
(input, _mag) = MAG::read_data(input, header.data_size)?;
mag = Some(_mag);
scale = _mag;
},
records::RTAG_ANGLE => {
let _angle_deg;
(input, _angle_deg) = ANGLE::read_data(input, header.data_size)?;
angle_deg = Some(_angle_deg);
angle_rad = _angle_deg.to_radians();
},
records::RTAG_COLROW => {
let mut _colrow;
@ -393,23 +814,13 @@ pub fn read_ref<'a>(
};
(input, header) = RecordHeader::read(input)?;
}
let inv_builder = ref_builder.field_builder::<BooleanBuilder>(1).unwrap();
inv_builder.append_option(invert_y);
let mag_builder = ref_builder.field_builder::<Float64Builder>(2).unwrap();
mag_builder.append_option(mag);
let angle_builder = ref_builder.field_builder::<Float64Builder>(3).unwrap();
angle_builder.append_option(angle_deg);
let (input, mut xy_iter) = XY::read_data(input, header.data_size)?;
let xx = xy_iter.next().unwrap();
let yy = xy_iter.next().unwrap();
let xy = ((xx as u32 as u64) << 32) | (yy as u32 as u64);
let xy_builder = ref_builder.field_builder::<UInt64Builder>(4).unwrap();
xy_builder.append_value(xy);
let (input, properties) = read_properties_vec(input)?;
let rep_builder = ref_builder.field_builder::<StructBuilder>(5).unwrap();
// println!("ref, {is_aref:?}");
if is_aref {
if colrow.is_none() {
return fail(input, "AREF without COLROW before XY".to_string())
@ -423,30 +834,28 @@ pub fn read_ref<'a>(
let xy0a = ((x0a as u32 as u64) << 32) | (y0a as u32 as u64);
let xy1a = ((x1a as u32 as u64) << 32) | (y1a as u32 as u64);
let xy0_builder = rep_builder.field_builder::<UInt64Builder>(0).unwrap();
xy0_builder.append_value(xy0a);
let xy1_builder = rep_builder.field_builder::<UInt64Builder>(1).unwrap();
xy1_builder.append_value(xy1a);
let counts = ((count0 as u16 as u32) << 16) | (count1 as u16 as u32);
let counts_builder = rep_builder.field_builder::<UInt32Builder>(2).unwrap();
counts_builder.append_value(counts);
Ok((input, RefRecord::ARef(ARefRecord {
target_id: *id,
invert_y,
scale,
angle_rad,
xy,
xy0: xy0a,
xy1: xy1a,
counts,
properties,
})))
} else {
let xy0_builder = rep_builder.field_builder::<UInt64Builder>(0).unwrap();
xy0_builder.append_null();
let xy1_builder = rep_builder.field_builder::<UInt64Builder>(1).unwrap();
xy1_builder.append_null();
let counts_builder = rep_builder.field_builder::<UInt32Builder>(2).unwrap();
counts_builder.append_null();
Ok((input, RefRecord::SRef(SRefRecord {
target_id: *id,
invert_y,
scale,
angle_rad,
xy,
properties,
})))
}
rep_builder.append(is_aref);
let props_builder = ref_builder.field_builder::<DListBuilder>(6).unwrap();
let (input, ()) = read_properties(input, props_builder)?;
ref_builder.append(true);
Ok((input, ()))
}
@ -490,6 +899,29 @@ pub fn read_properties<'a>(input: &'a [u8], props_builder: &mut DListBuilder) ->
Ok((input, ()))
}
fn read_properties_vec<'a>(input: &'a [u8]) -> IResult<'a, Vec<PropertyRecord>> {
let mut properties = Vec::<PropertyRecord>::new();
let (mut input, mut header) = RecordHeader::read(input)?;
while header.tag != ENDEL::tag() {
if header.tag == PROPATTR::tag() {
let key;
let value_bytes;
(input, key) = PROPATTR::read_data(input, header.data_size)?;
(input, value_bytes) = PROPVALUE::read(input)?;
properties.push(PropertyRecord {
key,
value: String::from_utf8(value_bytes).unwrap(),
});
}
(input, header) = RecordHeader::read(input)?;
}
Ok((input, properties))
}
/*
///

View file

@ -111,19 +111,43 @@ pub fn read_library(input: &[u8]) -> IResult<StructArray> {
));
let repetition_struct_t = DataType::Struct(Fields::from(vec![
let sref_struct_t = DataType::Struct(Fields::from(vec![
Field::new("target", DataType::UInt32, false),
Field::new("invert_y", DataType::Boolean, false),
Field::new("scale", DataType::Float64, false),
Field::new("angle_rad", DataType::Float64, false),
Field::new("xy", DataType::UInt64, false),
]));
let aref_struct_t = DataType::Struct(Fields::from(vec![
Field::new("target", DataType::UInt32, false),
Field::new("invert_y", DataType::Boolean, false),
Field::new("scale", DataType::Float64, false),
Field::new("angle_rad", DataType::Float64, false),
Field::new("xy", DataType::UInt64, false),
Field::new("xy0", DataType::UInt64, false),
Field::new("xy1", DataType::UInt64, false),
Field::new("counts", DataType::UInt32, false),
]));
let ref_struct_t = DataType::Struct(Fields::from(vec![
let sref_prop_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("invert_y", DataType::Boolean, false),
Field::new("scale", DataType::Float64, false),
Field::new("angle_rad", DataType::Float64, false),
Field::new("xy", DataType::UInt64, false),
Field::new("repetition", repetition_struct_t, true),
Field::new("properties", property_list_t.clone(), true),
]));
let aref_prop_struct_t = DataType::Struct(Fields::from(vec![
Field::new("target", DataType::UInt32, false),
Field::new("invert_y", DataType::Boolean, false),
Field::new("scale", DataType::Float64, false),
Field::new("angle_rad", DataType::Float64, false),
Field::new("xy", DataType::UInt64, false),
Field::new("xy0", DataType::UInt64, false),
Field::new("xy1", DataType::UInt64, false),
Field::new("counts", DataType::UInt32, false),
Field::new("properties", property_list_t.clone(), true),
]));
@ -147,9 +171,24 @@ pub fn read_library(input: &[u8]) -> IResult<StructArray> {
Field::new_list_field(DataType::Int32, false)
));
let boundary_struct_t = DataType::Struct(Fields::from(vec![
let boundary_batch_struct_t = DataType::Struct(Fields::from(vec![
Field::new("layer", DataType::UInt32, false),
Field::new("xy", coords_t.clone(), false),
Field::new("vertices", coords_t.clone(), false),
Field::new(
"vertex_offsets",
DataType::List(Arc::new(Field::new_list_field(DataType::UInt32, false))),
false,
),
]));
let rect_batch_struct_t = DataType::Struct(Fields::from(vec![
Field::new("layer", DataType::UInt32, false),
Field::new("rects", coords_t.clone(), false),
]));
let boundary_prop_struct_t = DataType::Struct(Fields::from(vec![
Field::new("layer", DataType::UInt32, false),
Field::new("vertices", coords_t.clone(), false),
Field::new("properties", property_list_t.clone(), true),
]));
@ -169,17 +208,36 @@ pub fn read_library(input: &[u8]) -> IResult<StructArray> {
Field::new("properties", property_list_t.clone(), true),
]));
let sref_list_t = DataType::List(Arc::new(
Field::new_list_field(sref_struct_t, false)
));
let ref_list_t = DataType::List(Arc::new(
Field::new_list_field(ref_struct_t, false)
let aref_list_t = DataType::List(Arc::new(
Field::new_list_field(aref_struct_t, false)
));
let sref_prop_list_t = DataType::List(Arc::new(
Field::new_list_field(sref_prop_struct_t, false)
));
let aref_prop_list_t = DataType::List(Arc::new(
Field::new_list_field(aref_prop_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 boundary_batch_list_t = DataType::List(Arc::new(
Field::new_list_field(boundary_batch_struct_t, false)
));
let rect_batch_list_t = DataType::List(Arc::new(
Field::new_list_field(rect_batch_struct_t, false)
));
let boundary_prop_list_t = DataType::List(Arc::new(
Field::new_list_field(boundary_prop_struct_t, false)
));
let path_list_t = DataType::List(Arc::new(
@ -207,8 +265,13 @@ pub fn read_library(input: &[u8]) -> IResult<StructArray> {
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("srefs", sref_list_t, false),
Field::new("arefs", aref_list_t, false),
Field::new("sref_props", sref_prop_list_t, false),
Field::new("aref_props", aref_prop_list_t, false),
Field::new("rect_batches", rect_batch_list_t, false),
Field::new("boundary_batches", boundary_batch_list_t, false),
Field::new("boundary_props", boundary_prop_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),