Skip to content

Commit

Permalink
[milestone] able to extract raw data from gds
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric committed Aug 2, 2021
1 parent 1eb6ab0 commit f6f83b9
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 65 deletions.
2 changes: 2 additions & 0 deletions src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub enum GDSIIVariant {
}

/// File header variant in GDSII
#[derive(Debug)]
pub enum FileHeader {
Header(i16), // 0x00_02
BgnLib([i16; 12]), // 0x01_02
Expand Down Expand Up @@ -89,6 +90,7 @@ impl Default for TuctosinHeader {
}
}

#[derive(Debug)]
pub enum Tuctosin {
ElfFlags(i16), // 0x26_01
Plex(i32), // 0x2F_03
Expand Down
5 changes: 2 additions & 3 deletions src/parser/basic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use super::ParseGDIIRes;
use byteorder::{BigEndian, ByteOrder, LittleEndian};
use byteorder::{BigEndian, ByteOrder};
use nom::bytes::streaming::{tag, take};
use nom::sequence::tuple;

// return valid data size(exclude two byte "size" and two byte "type")
pub(super) fn take_size(s: &[u8]) -> ParseGDIIRes<&[u8], usize> {
Expand All @@ -16,5 +15,5 @@ pub(super) fn take_type(s: &[u8]) -> ParseGDIIRes<&[u8], [u8; 2]> {
}

pub(super) fn end_tag(s: &[u8]) -> ParseGDIIRes<&[u8], &[u8]> {
tag([0x00, 0x00])(s)
tag([0x00, 0x04, 0x04, 0x00])(s)
}
106 changes: 46 additions & 60 deletions src/parser/variant_parser.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::basic::*;
use super::{ParseGDIIRes, ParseGDSIIError};
use super::ParseGDIIRes;
use crate::model::*;
use byteorder::{BigEndian, ByteOrder, LittleEndian};
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use nom::bytes::streaming::take;
use std::str;

use std::ascii;
use std::io::Cursor;
pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
let (s, size) = take_size(s)?;
let (s, d_type) = take_type(s)?;
Expand All @@ -28,45 +28,44 @@ pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
[0x01, 0x02] => {
assert!(d_size == 24usize, "mismatch data bgn length in file header");
let mut bgn = [0i16; 12];
// let byted = data.as_bytes();
for i in 0..12 {
bgn[i] = BigEndian::read_i16(&data)
}
BigEndian::read_i16_into(&data, &mut bgn);
GDSIIVariant::FileHeader(FileHeader::BgnLib(bgn))
}
[0x02, 0x06] => {
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::FileHeader(FileHeader::LibName(str_data.to_string()))
let escaped_ascii = data
.iter()
.map(|v| ascii::escape_default(*v).next().unwrap())
.collect();
GDSIIVariant::FileHeader(FileHeader::LibName(
String::from_utf8(escaped_ascii).unwrap(),
))
}
[0x1F, 0x06] => {
assert!(d_size == 90usize, "mismatch reflib length in file header");
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::FileHeader(FileHeader::RefLibs(str_data.to_string()))
let escaped_ascii = data
.iter()
.map(|v| ascii::escape_default(*v).next().unwrap())
.collect();
GDSIIVariant::FileHeader(FileHeader::RefLibs(
String::from_utf8(escaped_ascii).unwrap(),
))
}
[0x20, 0x06] => {
assert!(d_size == 176usize, "mismatch font length in file header");
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::FileHeader(FileHeader::Fonts(str_data.to_string()))
let escaped_ascii = data
.iter()
.map(|v| ascii::escape_default(*v).next().unwrap())
.collect();
GDSIIVariant::FileHeader(FileHeader::Fonts(String::from_utf8(escaped_ascii).unwrap()))
}
[0x23, 0x06] => {
assert!(
d_size == 44usize,
"mismatch attr_table length in file header"
);
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::FileHeader(FileHeader::AttrTable(str_data.to_string()))
GDSIIVariant::FileHeader(FileHeader::AttrTable(
String::from_utf8_lossy(data).to_string(),
))
}
[0x22, 0x02] => {
assert!(
Expand All @@ -82,11 +81,7 @@ pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
GDSIIVariant::FileHeader(FileHeader::Format(format))
}
[0x37, 0x06] => {
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::FileHeader(FileHeader::Mask(str_data.to_string()))
GDSIIVariant::FileHeader(FileHeader::Mask(String::from_utf8_lossy(data).to_string()))
}
[0x38, 0x00] => {
assert!(d_size == 0usize, "mismatch mask length in file header");
Expand All @@ -95,10 +90,7 @@ pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
[0x03, 0x05] => {
assert!(d_size == 16usize, "mismatch units length in file header");
let mut units = [0.0f64; 2];
// let byted = data.as_bytes();
for i in 0..2 {
units[i] = BigEndian::read_f64(&data)
}
BigEndian::read_f64_into(&data, &mut units);
GDSIIVariant::FileHeader(FileHeader::Units(units))
}
// File End
Expand All @@ -113,17 +105,17 @@ pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
"mismatch bgn_str length in module header"
);
let mut bgn = [0i16; 12];
for i in 0..12 {
bgn[i] = BigEndian::read_i16(&data)
}
BigEndian::read_i16_into(&data, &mut bgn);
GDSIIVariant::ModuleHeader(ModuleHeader::BgnStr(bgn))
}
[0x06, 0x06] => {
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::ModuleHeader(ModuleHeader::StrName(str_data.to_string()))
let escaped_ascii = data
.iter()
.map(|v| ascii::escape_default(*v).next().unwrap())
.collect();
GDSIIVariant::ModuleHeader(ModuleHeader::StrName(
String::from_utf8(escaped_ascii).unwrap(),
))
}
// Module End
[0x07, 0x00] => {
Expand Down Expand Up @@ -213,14 +205,16 @@ pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
let data_type = BigEndian::read_i16(&data);
GDSIIVariant::Tuctosin(Tuctosin::DataType(data_type))
}
// tuctosin body
// TODO: seek better solution
[0x10, 0x03] => {
assert!(d_size % 8 == 0, "mismatch x_y length in tuctosin body");
let mut reader = Cursor::new(data);
let mut shapes = vec![];
let shape_len = d_size / 8;
// let byted = data.as_bytes();
for _ in 0..shape_len {
let x = BigEndian::read_i32(&data);
let y = BigEndian::read_i32(&data);
let x = reader.read_i32::<BigEndian>().unwrap();
let y = reader.read_i32::<BigEndian>().unwrap();
shapes.push((x, y));
}
GDSIIVariant::Tuctosin(Tuctosin::Xy(shapes))
Expand All @@ -239,11 +233,7 @@ pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
GDSIIVariant::Tuctosin(Tuctosin::Width(width))
}
[0x12, 0x06] => {
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::Tuctosin(Tuctosin::Sname(str_data.to_string()))
GDSIIVariant::Tuctosin(Tuctosin::Sname(String::from_utf8_lossy(data).to_string()))
}
[0x1A, 0x01] => {
assert!(
Expand Down Expand Up @@ -286,13 +276,9 @@ pub(super) fn variant_parser(s: &[u8]) -> ParseGDIIRes<&[u8], GDSIIVariant> {
let pers = BigEndian::read_i16(&data);
GDSIIVariant::Tuctosin(Tuctosin::Persentation(pers))
}
[0x19, 0x06] => {
let str_data = match str::from_utf8(data) {
Ok(q) => q,
Err(_) => return Err(nom::Err::Error(ParseGDSIIError::Utf8Error)),
};
GDSIIVariant::Tuctosin(Tuctosin::AsciiString(str_data.to_string()))
}
[0x19, 0x06] => GDSIIVariant::Tuctosin(Tuctosin::AsciiString(
String::from_utf8_lossy(data).to_string(),
)),
[0x2A, 0x02] => {
assert!(
d_size == 2usize,
Expand Down
30 changes: 28 additions & 2 deletions tests/test1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,35 @@ use gds2_parser::parse_gds2;
#[test]
fn test_1() {
let gds2_data = parse_gds2(&format!(
"{}/testcases/sim_c2.gds",
"{}/testcases/sim_c1.gds",
std::env::var("CARGO_MANIFEST_DIR").unwrap(),
))
.unwrap();
println!("{:?}", gds2_data.structure_name);
println!(
"header: {}",
gds2_data
.header
.iter()
.map(|(k, v)| format!("{}:{:?} \n", k, v))
.collect::<String>()
);
println!("struct name: {:?}", gds2_data.structure_name);
}

#[test]
fn test_2() {
let gds2_data = parse_gds2(&format!(
"{}/testcases/sim_c6.gds",
std::env::var("CARGO_MANIFEST_DIR").unwrap(),
))
.unwrap();
println!(
"header: {}",
gds2_data
.header
.iter()
.map(|(k, v)| format!("{}:{:?} \n", k, v))
.collect::<String>()
);
println!("struct name: {:?}", gds2_data.structure_name);
}

0 comments on commit f6f83b9

Please sign in to comment.