| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  | ///
 | 
					
						
							|  |  |  | /// File-level read/write functionality.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | use std::io::Write;
 | 
					
						
							| 
									
										
										
										
											2025-04-10 01:07:11 -07:00
										 |  |  | //use std::collections::HashMap;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-17 18:38:40 -08:00
										 |  |  | pub use crate::record;
 | 
					
						
							|  |  |  | pub use crate::record::{RecordHeader, Record};
 | 
					
						
							|  |  |  | pub use crate::records;
 | 
					
						
							|  |  |  | pub use crate::elements;
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  | pub use crate::elements::{read_elements, DListBuilder, FListBuilder};
 | 
					
						
							| 
									
										
										
										
											2024-12-17 18:38:40 -08:00
										 |  |  | pub use crate::basic::{IResult, OResult, take_bytes, fail};
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | use std::string::String;
 | 
					
						
							|  |  |  | use std::collections::HashMap;
 | 
					
						
							|  |  |  | use std::sync::Arc;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | use arrow::datatypes::{DataType, Field, Fields};
 | 
					
						
							|  |  |  | use arrow::array::{
 | 
					
						
							|  |  |  |     StructBuilder, StringBuilder, UInt64Builder, UInt32Builder, Int16Builder, Float64Builder,
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |     StructArray,
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | };
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Representation of the GDS file header.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// File header records: HEADER BGNLIB LIBNAME UNITS
 | 
					
						
							|  |  |  | ///    Optional records are ignored if present and never written.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Version is written as `600`.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | #[derive(Debug, Clone)]
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | pub struct FileHeader {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     /// Number of user units in one database unit
 | 
					
						
							|  |  |  |     user_units_per_db_unit: f64,
 | 
					
						
							|  |  |  |     /// Number of meters in one database unit
 | 
					
						
							|  |  |  |     meters_per_db_unit: f64,
 | 
					
						
							|  |  |  |     /// Last-modified time [y, m, d, h, m, s]
 | 
					
						
							|  |  |  |     mod_time: [i16; 6],
 | 
					
						
							|  |  |  |     /// Last-accessed time [y, m, d, h, m, s]
 | 
					
						
							|  |  |  |     acc_time: [i16; 6],
 | 
					
						
							|  |  |  |     /// Library name
 | 
					
						
							|  |  |  |     name: Vec<u8>,
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl FileHeader {
 | 
					
						
							|  |  |  |     pub fn new(name: &[u8], meters_per_db_unit: f64, user_units_per_db_unit: f64) -> Self {
 | 
					
						
							|  |  |  |         FileHeader{
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |             mod_time: [0, 1, 1, 0, 0, 0],
 | 
					
						
							|  |  |  |             acc_time: [0, 1, 1, 0, 0, 0],
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |             name: name.to_owned(),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |             user_units_per_db_unit,
 | 
					
						
							|  |  |  |             meters_per_db_unit,
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     /// Read and construct a header from the provided input.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Args:
 | 
					
						
							|  |  |  |     ///     input: Seekable input to read from
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Returns:
 | 
					
						
							|  |  |  |     ///     FileHeader object
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     pub fn read(input: &[u8]) -> IResult<Self> {
 | 
					
						
							|  |  |  |         let (input, _version) = records::HEADER::read(input)?;
 | 
					
						
							|  |  |  |         let (input, [mod_time, acc_time]) = records::BGNLIB::read(input)?;
 | 
					
						
							|  |  |  |         let (input, name) = records::LIBNAME::skip_and_read(input)?;
 | 
					
						
							|  |  |  |         let (input, (uu, dbu)) = records::UNITS::skip_and_read(input)?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         Ok((input, FileHeader{
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |             mod_time,
 | 
					
						
							|  |  |  |             acc_time,
 | 
					
						
							|  |  |  |             name,
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |             user_units_per_db_unit: uu,
 | 
					
						
							|  |  |  |             meters_per_db_unit: dbu,
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         }))
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     /// Write the header to a input
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Args:
 | 
					
						
							|  |  |  |     ///     input: input to write to
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Returns:
 | 
					
						
							|  |  |  |     ///     number of bytes written
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     pub fn write<W: Write>(&self, ww: &mut W) -> OResult {
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |         let mut size = 0;
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         size += records::HEADER::write(ww, &600)?;
 | 
					
						
							|  |  |  |         size += records::BGNLIB::write(ww, &[self.mod_time, self.acc_time])?;
 | 
					
						
							|  |  |  |         size += records::LIBNAME::write(ww, &self.name)?;
 | 
					
						
							|  |  |  |         size += records::UNITS::write(ww, &(self.user_units_per_db_unit, self.meters_per_db_unit))?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |         Ok(size)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | pub fn read_library(input: &[u8]) -> IResult<StructArray> {
 | 
					
						
							|  |  |  |     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![
 | 
					
						
							| 
									
										
										
										
											2025-04-22 20:16:38 -07:00
										 |  |  |         Field::new("xy0", DataType::UInt64, false),
 | 
					
						
							|  |  |  |         Field::new("xy1", DataType::UInt64, false),
 | 
					
						
							|  |  |  |         Field::new("counts", DataType::UInt32, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |     ]));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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),
 | 
					
						
							| 
									
										
										
										
											2025-04-22 20:16:38 -07:00
										 |  |  |         Field::new("xy", DataType::UInt64, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         Field::new("repetition", repetition_struct_t, true),
 | 
					
						
							|  |  |  |         Field::new("properties", property_list_t.clone(), true),
 | 
					
						
							|  |  |  |     ]));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let text_struct_t = DataType::Struct(Fields::from(vec![
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |         Field::new("layer", DataType::UInt32, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         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),
 | 
					
						
							| 
									
										
										
										
											2025-04-22 20:16:38 -07:00
										 |  |  |         Field::new("xy", DataType::UInt64, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         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![
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |         Field::new("layer", DataType::UInt32, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         Field::new("xy", coords_t.clone(), false),
 | 
					
						
							|  |  |  |         Field::new("properties", property_list_t.clone(), true),
 | 
					
						
							|  |  |  |     ]));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let path_struct_t = DataType::Struct(Fields::from(vec![
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |         Field::new("layer", DataType::UInt32, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |         Field::new("path_type", DataType::Int16, true),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         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![
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |         Field::new("layer", DataType::UInt32, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         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 name_list_t = DataType::List(Arc::new(
 | 
					
						
							|  |  |  |         Field::new_list_field(DataType::Utf8, false)
 | 
					
						
							|  |  |  |     ));
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |     let layer_list_t = DataType::List(Arc::new(
 | 
					
						
							|  |  |  |         Field::new_list_field(DataType::UInt32, false)
 | 
					
						
							|  |  |  |     ));
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |     let time_t = DataType::FixedSizeList(Arc::new(
 | 
					
						
							|  |  |  |         Field::new_list_field(DataType::Int16, false),
 | 
					
						
							|  |  |  |         ),
 | 
					
						
							|  |  |  |         6,
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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),
 | 
					
						
							|  |  |  |     ]));
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |     let cells_list_t = DataType::List(Arc::new(
 | 
					
						
							|  |  |  |         Field::new_list_field(cell_struct_t, false)
 | 
					
						
							|  |  |  |     ));
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |     let mut lib_builder = StructBuilder::from_fields(vec![
 | 
					
						
							|  |  |  |             Field::new("meters_per_db_unit", DataType::Float64, false),
 | 
					
						
							|  |  |  |             Field::new("user_units_per_db_unit", DataType::Float64, false),
 | 
					
						
							|  |  |  |             Field::new("lib_name", DataType::Utf8, false),
 | 
					
						
							|  |  |  |             Field::new("mod_time", time_t.clone(), false),
 | 
					
						
							|  |  |  |             Field::new("acc_time", time_t.clone(), false),
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |             Field::new("cells", cells_list_t, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |             Field::new("cell_names", name_list_t, false),
 | 
					
						
							|  |  |  |             Field::new("layers", layer_list_t, false),
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         ],
 | 
					
						
							|  |  |  |         0,
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let (input, header) = FileHeader::read(input)?;
 | 
					
						
							|  |  |  |     let dbu_builder = lib_builder.field_builder::<Float64Builder>(0).unwrap();
 | 
					
						
							|  |  |  |     dbu_builder.append_value(header.meters_per_db_unit);
 | 
					
						
							|  |  |  |     let uu_builder = lib_builder.field_builder::<Float64Builder>(1).unwrap();
 | 
					
						
							|  |  |  |     uu_builder.append_value(header.user_units_per_db_unit);
 | 
					
						
							|  |  |  |     let libname_builder = lib_builder.field_builder::<StringBuilder>(2).unwrap();
 | 
					
						
							|  |  |  |     libname_builder.append_value(String::from_utf8(header.name).unwrap());
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |     let mtl_builder = lib_builder.field_builder::<FListBuilder>(3).unwrap();
 | 
					
						
							|  |  |  |     let mt_builder = mtl_builder.values().as_any_mut().downcast_mut::<Int16Builder>().unwrap();
 | 
					
						
							|  |  |  |     mt_builder.append_values(&header.mod_time, &[true; 6]);
 | 
					
						
							|  |  |  |     mtl_builder.append(true);
 | 
					
						
							|  |  |  |     let atl_builder = lib_builder.field_builder::<FListBuilder>(4).unwrap();
 | 
					
						
							|  |  |  |     let at_builder = atl_builder.values().as_any_mut().downcast_mut::<Int16Builder>().unwrap();
 | 
					
						
							|  |  |  |     at_builder.append_values(&header.acc_time, &[true; 6]);
 | 
					
						
							|  |  |  |     atl_builder.append(true);
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     let mut names = HashMap::<String, u32>::new();
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |     let mut layers = HashMap::<u32, u32>::new();
 | 
					
						
							|  |  |  |     let cells_builder = lib_builder.field_builder::<DListBuilder>(5).unwrap();
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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();
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |             println!("{name}");
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |             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::<StructBuilder>().unwrap();
 | 
					
						
							|  |  |  |             let id_builder = cell_builder.field_builder::<UInt32Builder>(0).unwrap();
 | 
					
						
							|  |  |  |             id_builder.append_value(*id);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             let offset_builder = cell_builder.field_builder::<UInt64Builder>(1).unwrap();
 | 
					
						
							|  |  |  |             offset_builder.append_value(position.try_into().unwrap());
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |             (input, _) = read_elements(input, cell_builder, &mut names, &mut layers)?;
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |             cell_builder.append(true);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |         (input, header) = RecordHeader::read(input)?;
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |     cells_builder.append(true);
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     let mut ids: HashMap<u32, String> = names.into_iter().map(|(kk, vv)| (vv, kk)).collect();
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |     let names_builder = lib_builder.field_builder::<DListBuilder>(6).unwrap();
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |     let name_builder = names_builder.values().as_any_mut().downcast_mut::<StringBuilder>().unwrap();
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |     for id in 0..ids.len() {
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |         name_builder.append_value(ids.remove(&id.try_into().unwrap()).unwrap());
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2025-04-12 12:06:36 -07:00
										 |  |  |     names_builder.append(true);
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-20 23:21:54 -07:00
										 |  |  |     let mut layer_ids: HashMap<u32, u32> = layers.into_iter().map(|(kk, vv)| (vv, kk)).collect();
 | 
					
						
							|  |  |  |     let layers_builder = lib_builder.field_builder::<DListBuilder>(7).unwrap();
 | 
					
						
							|  |  |  |     let layer_builder = layers_builder.values().as_any_mut().downcast_mut::<UInt32Builder>().unwrap();
 | 
					
						
							|  |  |  |     for layer_id in 0..layer_ids.len() {
 | 
					
						
							|  |  |  |         layer_builder.append_value(layer_ids.remove(&layer_id.try_into().unwrap()).unwrap());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     layers_builder.append(true);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-11 11:18:56 -07:00
										 |  |  |     lib_builder.append(true);
 | 
					
						
							|  |  |  |     let lib = lib_builder.finish();
 | 
					
						
							|  |  |  |     Ok((input, lib))
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-10 01:07:11 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  | ///
 | 
					
						
							|  |  |  | /// Scan through a GDS file, building a table of
 | 
					
						
							|  |  |  | ///   {b'structure_name': byte_offset}.
 | 
					
						
							|  |  |  | /// The intent of this function is to enable random access
 | 
					
						
							|  |  |  | ///  and/or partial (structure-by-structure) reads.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Args:
 | 
					
						
							|  |  |  | ///     input: Seekable input to read from. Should be positioned
 | 
					
						
							|  |  |  | ///             before the first structure record, but possibly
 | 
					
						
							|  |  |  | ///             already past the file header.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | pub fn scan_structs(input: &[u8]) -> IResult<HashMap::<Vec<u8>, usize>> {
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     let input_size = input.len();
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     let mut positions = HashMap::new();
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     let (mut input, mut header) = RecordHeader::read(input)?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     while header.tag != records::RTAG_ENDLIB {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         (input, _) = take_bytes(input, header.data_size)?;
 | 
					
						
							|  |  |  |         if header.tag == records::RTAG_BGNSTR {
 | 
					
						
							|  |  |  |             let name;
 | 
					
						
							|  |  |  |             (input, name) = records::STRNAME::read(input)?;
 | 
					
						
							|  |  |  |             if positions.contains_key(&name) {
 | 
					
						
							|  |  |  |                 return fail(input, format!("Duplicate structure name: {:?}", name));
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |             }
 | 
					
						
							|  |  |  |             let position = input_size - input.len();
 | 
					
						
							|  |  |  |             positions.insert(name, position);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         (input, header) = RecordHeader::read(input)?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     Ok((input, positions))
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2025-04-10 01:07:11 -07:00
										 |  |  | */
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-10 01:07:11 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  | #[derive(Debug, Clone)]
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | pub struct Cell {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     name: Vec<u8>,
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     boundaries: Vec<elements::Boundary>,
 | 
					
						
							|  |  |  |     paths: Vec<elements::Path>,
 | 
					
						
							|  |  |  |     nodes: Vec<elements::Node>,
 | 
					
						
							|  |  |  |     boxes: Vec<elements::GDSBox>,
 | 
					
						
							|  |  |  |     texts: Vec<elements::Text>,
 | 
					
						
							|  |  |  |     refs: Vec<elements::Reference>,
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl Cell {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     /// Build an empty cell
 | 
					
						
							|  |  |  |     pub fn new(name: Vec<u8>) -> Self {
 | 
					
						
							|  |  |  |         Cell{
 | 
					
						
							|  |  |  |             name: name,
 | 
					
						
							|  |  |  |             boundaries: Vec::new(),
 | 
					
						
							|  |  |  |             paths: Vec::new(),
 | 
					
						
							|  |  |  |             nodes: Vec::new(),
 | 
					
						
							|  |  |  |             boxes: Vec::new(),
 | 
					
						
							|  |  |  |             texts: Vec::new(),
 | 
					
						
							|  |  |  |             refs: Vec::new(),
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Skip to the next structure and attempt to read it.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Args:
 | 
					
						
							|  |  |  |     ///     input: Seekable input to read from.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Returns:
 | 
					
						
							|  |  |  |     ///     (name, elements) if a structure was found.
 | 
					
						
							|  |  |  |     ///     None if no structure was found before the end of the library.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     pub fn read(input: &[u8]) -> IResult<Option<Cell>> {
 | 
					
						
							|  |  |  |         let (input, success) = records::BGNSTR::skip_past(input)?;
 | 
					
						
							|  |  |  |         if !success {
 | 
					
						
							|  |  |  |             return Ok((input, None))
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let (input, name) = records::STRNAME::read(input)?;
 | 
					
						
							|  |  |  |         let mut cell = Cell::new(name);
 | 
					
						
							|  |  |  |         let (input, _) = cell.read_elements(input)?;
 | 
					
						
							|  |  |  |         Ok((input, Some(cell)))
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Read elements from the input until an ENDSTR
 | 
					
						
							|  |  |  |     ///   record is encountered. The ENDSTR record is also
 | 
					
						
							|  |  |  |     ///   consumed.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Args:
 | 
					
						
							|  |  |  |     ///     input: Seekable input to read from.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Returns:
 | 
					
						
							|  |  |  |     ///     List of element objects.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     pub fn read_elements<'a>(&mut self, input: &'a [u8]) -> IResult<'a, ()> {
 | 
					
						
							|  |  |  |         let (mut input, mut header) = RecordHeader::read(input)?;
 | 
					
						
							|  |  |  |         while header.tag != records::RTAG_ENDSTR {
 | 
					
						
							|  |  |  |             match header.tag {
 | 
					
						
							|  |  |  |                 records::RTAG_BOUNDARY => {
 | 
					
						
							|  |  |  |                     let boundary;
 | 
					
						
							|  |  |  |                     (input, _) = records::BOUNDARY::read(input)?;
 | 
					
						
							|  |  |  |                     (input, boundary) = elements::Boundary::read(input)?;
 | 
					
						
							|  |  |  |                     self.boundaries.push(boundary);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 records::RTAG_PATH => {
 | 
					
						
							|  |  |  |                     let path;
 | 
					
						
							|  |  |  |                     (input, _) = records::PATH::read(input)?;
 | 
					
						
							|  |  |  |                     (input, path) = elements::Path::read(input)?;
 | 
					
						
							|  |  |  |                     self.paths.push(path);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 records::RTAG_NODE => {
 | 
					
						
							|  |  |  |                     let node;
 | 
					
						
							|  |  |  |                     (input, _) = records::NODE::read(input)?;
 | 
					
						
							|  |  |  |                     (input, node) = elements::Node::read(input)?;
 | 
					
						
							|  |  |  |                     self.nodes.push(node);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 records::RTAG_BOX => {
 | 
					
						
							|  |  |  |                     let gds_box;
 | 
					
						
							|  |  |  |                     (input, _) = records::BOX::read(input)?;
 | 
					
						
							|  |  |  |                     (input, gds_box) = elements::GDSBox::read(input)?;
 | 
					
						
							|  |  |  |                     self.boxes.push(gds_box);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 records::RTAG_TEXT => {
 | 
					
						
							|  |  |  |                     let txt;
 | 
					
						
							|  |  |  |                     (input, _) = records::TEXT::read(input)?;
 | 
					
						
							|  |  |  |                     (input, txt) = elements::Text::read(input)?;
 | 
					
						
							|  |  |  |                     self.texts.push(txt);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 records::RTAG_SREF => {
 | 
					
						
							|  |  |  |                     let sref;
 | 
					
						
							|  |  |  |                     (input, _) = records::SREF::read(input)?;
 | 
					
						
							|  |  |  |                     (input, sref) = elements::Reference::read(input)?;
 | 
					
						
							|  |  |  |                     self.refs.push(sref);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 records::RTAG_AREF => {
 | 
					
						
							|  |  |  |                     let aref;
 | 
					
						
							|  |  |  |                     (input, _) = records::AREF::read(input)?;
 | 
					
						
							|  |  |  |                     (input, aref) = elements::Reference::read(input)?;
 | 
					
						
							|  |  |  |                     self.refs.push(aref);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 _ => {
 | 
					
						
							|  |  |  |                     // don't care, skip
 | 
					
						
							|  |  |  |                     (input, _) = take_bytes(input, header.data_size)?;
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |             (input, header) = RecordHeader::read(input)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         Ok((input, ()))
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Write a structure to the provided input.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Args:
 | 
					
						
							|  |  |  |     ///     name: Structure name (ascii-encoded).
 | 
					
						
							|  |  |  |     ///     elements: List of Elements containing the geometry and text in this struct.
 | 
					
						
							|  |  |  |     ///     cre_time: Creation time (optional).
 | 
					
						
							|  |  |  |     ///     mod_time: Modification time (optional).
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Return:
 | 
					
						
							|  |  |  |     ///     Number of bytes written
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     pub fn write<W: Write>(
 | 
					
						
							|  |  |  |             &self,
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |             ww: &mut W,
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |             cre_time: Option<[i16; 6]>,
 | 
					
						
							|  |  |  |             mod_time: Option<[i16; 6]>,
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |             ) -> OResult {
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |         let mut size = 0;
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         size += records::BGNSTR::write(ww, &[cre_time.unwrap_or(DEFAULT_DATE),
 | 
					
						
							|  |  |  |                                              mod_time.unwrap_or(DEFAULT_DATE)])?;
 | 
					
						
							|  |  |  |         size += records::STRNAME::write(ww, &self.name)?;
 | 
					
						
							|  |  |  |         size += self.write_elements(ww)?;
 | 
					
						
							|  |  |  |         size += records::ENDSTR::write(ww, &())?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |         Ok(size)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     pub fn write_elements<W: Write>(&self, ww: &mut W) -> OResult {
 | 
					
						
							|  |  |  |         let mut size = 0;
 | 
					
						
							|  |  |  |         for boundary in &self.boundaries {
 | 
					
						
							|  |  |  |             size += boundary.write(ww)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         for path in &self.paths {
 | 
					
						
							|  |  |  |             size += path.write(ww)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         for node in &self.nodes {
 | 
					
						
							|  |  |  |             size += node.write(ww)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         for gds_box in &self.boxes {
 | 
					
						
							|  |  |  |             size += gds_box.write(ww)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         for text in &self.texts {
 | 
					
						
							|  |  |  |             size += text.write(ww)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         for reference in &self.refs {
 | 
					
						
							|  |  |  |             size += reference.write(ww)?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         Ok(size)
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2025-04-10 01:07:11 -07:00
										 |  |  | */
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 16:41:43 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  | ///
 | 
					
						
							|  |  |  | /// Scan through a GDS file, building a table of instance counts
 | 
					
						
							|  |  |  | ///   `{b'structure_name': {b'ref_name': count}}`.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// This is intended to provide a fast overview of the file's
 | 
					
						
							|  |  |  | ///  contents without performing a full read of all elements.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Args:
 | 
					
						
							|  |  |  | ///     input: Seekable input to read from. Should be positioned
 | 
					
						
							|  |  |  | ///             before the first structure record, but possibly
 | 
					
						
							|  |  |  | ///             already past the file header.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | pub fn scan_hierarchy(input: &[u8]) -> IResult<HashMap::<Vec<u8>, HashMap::<Vec<u8>, u32>>> {
 | 
					
						
							|  |  |  |     let mut structures = HashMap::new();
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 16:41:43 -07:00
										 |  |  |     let mut ref_name = None;
 | 
					
						
							|  |  |  |     let mut ref_count = None;
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     let (mut input, mut header) = RecordHeader::read(input)?;
 | 
					
						
							| 
									
										
										
										
											2022-05-08 16:41:43 -07:00
										 |  |  |     let mut cur_structure = HashMap::new();
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     while header.tag != records::RTAG_ENDLIB {
 | 
					
						
							|  |  |  |         match header.tag {
 | 
					
						
							|  |  |  |             records::RTAG_BGNSTR => {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |                 (input, _) = take_bytes(input, header.data_size)?;
 | 
					
						
							|  |  |  |                 let result = records::STRNAME::read(input)?;
 | 
					
						
							|  |  |  |                 input = result.0;
 | 
					
						
							|  |  |  |                 let name = result.1;
 | 
					
						
							|  |  |  |                 if structures.contains_key(&name) {
 | 
					
						
							|  |  |  |                     return fail(input, format!("Duplicate structure name: {:?}", name));
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |                 }
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |                 let mut cur_structure = HashMap::new();
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |                 structures.insert(name, cur_structure);
 | 
					
						
							|  |  |  |                 ref_name = None;
 | 
					
						
							|  |  |  |                 ref_count = None;
 | 
					
						
							|  |  |  |             },
 | 
					
						
							|  |  |  |             records::RTAG_SNAME => {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |                 let result = records::SNAME::read_data(input, header.data_size)?;
 | 
					
						
							|  |  |  |                 input = result.0;
 | 
					
						
							|  |  |  |                 ref_name = Some(result.1);
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |             },
 | 
					
						
							|  |  |  |             records::RTAG_COLROW => {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |                 let result = records::COLROW::read_data(input, header.data_size)?;
 | 
					
						
							|  |  |  |                 input = result.0;
 | 
					
						
							|  |  |  |                 let (col, row) = (result.1[0], result.1[1]);
 | 
					
						
							|  |  |  |                 ref_count = Some((col * row) as u32);
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |             },
 | 
					
						
							|  |  |  |             records::RTAG_ENDEL => {
 | 
					
						
							|  |  |  |                 *cur_structure.entry(ref_name.unwrap()).or_insert(0) += ref_count.unwrap_or(1);
 | 
					
						
							|  |  |  |             },
 | 
					
						
							|  |  |  |             _ => {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |                 (input, _) = take_bytes(input, header.data_size)?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |             },
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         (input, header) = RecordHeader::read(input)?;
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     Ok((input, structures))
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2022-05-08 16:41:43 -07:00
										 |  |  | */
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 16:41:43 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  | pub fn count_ref(input: &[u8]) -> IResult<Option((Vec<u8>, u32))> {
 | 
					
						
							|  |  |  |     let (input, found_struc) = records::BGNSTR.skip_past(input)?;
 | 
					
						
							| 
									
										
										
										
											2022-05-08 16:41:43 -07:00
										 |  |  |     if !found_struc {
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |         return Ok((input, None))
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     let mut cur_structure = HashMap::new();
 | 
					
						
							|  |  |  |     let (input, name) = records::STRNAME::read(input)?;
 | 
					
						
							|  |  |  |     if structures.contains_key(&name) {
 | 
					
						
							|  |  |  |         return fail(input, format!("Duplicate structure name: {:?}", name));
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let (mut input, mut header) = RecordHeader::read(input)?;
 | 
					
						
							|  |  |  |     while header.tag != records::RTAG_ENDSTR {
 | 
					
						
							|  |  |  |         let mut ref_name = None;
 | 
					
						
							|  |  |  |         let mut ref_count = None;
 | 
					
						
							|  |  |  |         while header.tag != records::RTAG_ENDEL {
 | 
					
						
							|  |  |  |             match header.tag {
 | 
					
						
							|  |  |  |                 records::RTAG_SNAME => {
 | 
					
						
							|  |  |  |                     let result = records::SNAME::read_data(input1, header.data_size)?;
 | 
					
						
							|  |  |  |                     input1 = result.0;
 | 
					
						
							|  |  |  |                     ref_name = Some(result.1);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 records::RTAG_COLROW => {
 | 
					
						
							|  |  |  |                     let result = records::COLROW::read_data(input1, header.data_size)?;
 | 
					
						
							|  |  |  |                     input1 = result.0;
 | 
					
						
							|  |  |  |                     let (col, row) = (result.1[0], result.1[1]);
 | 
					
						
							|  |  |  |                     ref_count = Some((col * row) as u32);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |                 _ => {
 | 
					
						
							|  |  |  |                     (input1, _) = take_bytes(input1, header.data_size)?;
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |             (input1, header) = RecordHeader::read(input1)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         // got ENDEL, update count for this reference
 | 
					
						
							|  |  |  |         *cur_structure.entry(ref_name.unwrap()).or_insert(0) += ref_count.unwrap_or(1);
 | 
					
						
							|  |  |  |         (input1, header) = RecordHeader::read(input1)?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2022-03-20 16:28:34 -07:00
										 |  |  |     structures.insert(name, cur_structure);
 | 
					
						
							|  |  |  |     (input, header) = RecordHeader::read(input1)?;
 | 
					
						
							| 
									
										
										
										
											2021-12-18 21:05:00 -08:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2022-05-08 16:41:43 -07:00
										 |  |  | */
 |