pub mod gds_error;
pub mod gds_model;
mod gds_parser;
mod gds_reader;
mod gds_record;
mod gds_writer;
use std::error::Error;
use std::fs::read;
use std::path;
pub fn read_gdsii<T: AsRef<path::Path>>(
gds_file: T,
) -> Result<Box<gds_model::Lib>, Box<dyn Error>> {
let buff = read(gds_file)?;
let byte_len = buff.len();
if byte_len < 4usize {
return Result::Err(Box::new(gds_error::gds_err(
"not valid gds file, file size less than 4 byte",
)));
}
if let gds_record::HEADER = &buff[2..4] {
} else {
return Result::Err(Box::new(gds_error::gds_err(
"not valid gds file, no valid gds header section found",
)));
}
let mut idx: usize = 0;
let mut record_len: usize;
let mut records: Vec<gds_record::Record> = Vec::new();
while idx < byte_len {
record_len = u16::from_be_bytes(match buff[idx..idx + 2].try_into() {
Ok(v) => v,
Err(err) => {
return Result::Err(Box::new(gds_error::gds_err(&format!(
"transfer gds record failed at {:#08x}:{:#08x}: {}",
idx,
idx + 2,
err
))))
}
}) as usize;
if record_len == 0 {
return Result::Err(Box::new(gds_error::gds_err(&format!(
"not valid gds record length at {:#08x}:{:#08x}: zero length",
idx,
idx + 2
))));
}
match gds_reader::record_type(&buff[idx..idx + record_len]) {
Ok(r) => records.push(r),
Err(err) => {
return Err(Box::new(gds_error::gds_err(&format!(
"parse error at byte offset range {:#08x}:{:#08x}: {}",
idx,
idx + record_len,
err
))))
}
}
if let Some(gds_record::Record::EndLib) = records.last() {
break;
}
idx += record_len;
}
if records.len() == 0 {
return Result::Err(Box::new(gds_error::gds_err(
"not valid gds file, no any valid records found",
)));
}
Ok(gds_parser::parse_gds(&records)?)
}