libreda-oasis 0.0.1

OASIS input/output for libreda-db.
Documentation
extern crate libreda_oasis;
extern crate libreda_db;

use std::fs::File;

use libreda_oasis::*;
use libreda_db::prelude::{Layout, WithProperties};
use std::rc::Rc;

// TODO: Port unittests from KLayout.


fn test_read(test_name: &str) {
    let mut f = File::open(format!("./tests/klayout_test_data/t{}.oas", test_name)).unwrap();
    let mut layout = Layout::new();

    let reader = OASISStreamReader::default();
    let result = reader.read_layout(&mut f, &mut layout);

    dbg!(&layout);
    dbg!(&result);

    assert!(result.is_ok());
}

// TODO: Does not work yet because resolution is expected to be a positive integer value.
// #[test]
// fn test1_empty_file() {
//     test_read("1.1");
//     test_read("1.2");
//     test_read("1.3");
//     test_read("1.4");
//     test_read("1.5");
// }


#[test]
fn test2_cells() {
    test_read("2.1");
    test_read("2.2");
    test_read("2.4");
}

#[test]
#[should_panic]
fn test2_3_cells() {
    test_read("2.3"); // MUST FAIL
}

#[test]
#[should_panic]
fn test2_5_cells() {
    test_read("2.5"); // MUST FAIL
}

#[test]
fn test3_texts() {
    test_read("3.1");
}

#[test]
fn test4_rectangles() {
    test_read("4.1");
}

#[test]
fn test5_polygons() {
    // Test RECTANGLE.
    test_read("5.1");
}

#[test]
fn test6_paths() {
    // Test PATH.
    test_read("6.1");
}

#[test]
fn test8_placements() {
    test_read("8.1");
    test_read("8.2");
    // test_read("8.3");
    // test_read("8.4");
    // test_read("8.5");
    // // test_read("8.6");
    // test_read("8.7");
    // // test_read("8.8");
}

#[test]
fn test11_properties() {
    test_read("11.1");
    test_read("11.2");
    test_read("11.3");
    test_read("11.4");
}


// #[test]
// fn test13_layernames() {
//     test_read("13.1");
// }

#[test]
fn test_load_std_cell() {
    let filename = "INVX1_no_compression.oas";
    dbg!(format!("./tests/data/{}", filename));
    let mut f = File::open(format!("./tests/data/{}", filename)).unwrap();
    let mut layout = Layout::new();

    let result = OASISStreamReader::default()
        .read_layout(&mut f, &mut layout);

    dbg!(&layout);
    dbg!(&result);

    assert!(result.is_ok());
}

#[test]
fn test_load_and_store_std_cell() {
    let filename = "INVX1_no_compression.oas";
    dbg!(format!("./tests/data/{}", filename));
    let mut f = File::open(format!("./tests/data/{}", filename)).unwrap();
    let mut layout = Layout::new();

    let result = OASISStreamReader::default()
        .read_layout(&mut f, &mut layout);

    dbg!(&result);

    assert!(result.is_ok());

    // Write.
    let filename = "INVX1_no_compression_out.oas";
    dbg!(format!("./tests/data/{}", filename));
    let mut f = File::create(format!("./tests/data/{}", filename)).unwrap();

    let writer = OASISStreamWriter::default();
    let write_result = writer.write_layout(&mut f, &layout);

    dbg!(&write_result);
    assert!(write_result.is_ok());
}

#[test]
fn test_load_and_store_hierarchical_cell() {
    let filename = "three_cell_layout.oas";
    dbg!(format!("./tests/data/{}", filename));
    let mut f = File::open(format!("./tests/data/{}", filename)).unwrap();
    let mut layout = Layout::new();

    let result = OASISStreamReader::default()
        .read_layout(&mut f, &mut layout);

    dbg!(&result);

    assert!(result.is_ok());

    // Write.
    let filename = "three_cell_layout_out.oas";
    dbg!(format!("./tests/data/{}", filename));
    let mut f = File::create(format!("./tests/data/{}", filename)).unwrap();

    let write_result = OASISStreamWriter::default()
        .write_layout(&mut f, &layout);

    dbg!(&write_result);
    assert!(write_result.is_ok());
}


#[test]
fn test_load_layout_with_properties() {
    let filename = "simple_with_properties.oas";
    dbg!(format!("./tests/data/{}", filename));
    let mut f = File::open(format!("./tests/data/{}", filename)).unwrap();
    let mut layout = Layout::new();

    let result = OASISStreamReader::default()
        .read_layout(&mut f, &mut layout);

    dbg!(&result);

    assert!(result.is_ok());

    // Get GDS standard property from the layout.
    let top_cell_name = layout.property_str("S_TOP_CELL").unwrap();
    assert_eq!(top_cell_name.as_str(), "TOP");

    let top = layout.cell_by_name("TOP").unwrap();
    let sub = layout.cell_by_name("SUB").unwrap();

    // Test accessing the properties.
    assert!(sub.property("name").is_some());
    assert_eq!(sub.property_str("name").unwrap(), Rc::new("MySubCell1".to_string()));

    for inst in top.each_inst() {
        assert!(inst.property("name").is_some())
    }

    // The shapes in the cell 'SUB' should all have a property 'name'.
    let layer = layout.find_layer(1, 0).unwrap();
    for shape in sub.each_shape(layer) {
        assert!(shape.property("name").is_some())
    }
}

// #[test]
// fn test_load_and_store_big_layout() {
//     // This test could be very slow because of the debug output.
//
//     let filename = "big_layout.oas";
//     dbg!(format!("./tests/data/{}", filename));
//     let mut f = File::open(format!("./tests/data/{}", filename)).unwrap();
//     let mut layout = Layout::new();
//     let mut buf = BufReader::new(f);
//     let result = read_layout(&mut buf, &mut layout);
//
//     dbg!(&result);
//
//     assert!(result.is_ok());
//
//     // Write.
//     let filename = "big_layout.out.oas";
//     dbg!(format!("./tests/data/{}", filename));
//     let mut f = File::create(format!("./tests/data/{}", filename)).unwrap();
//     let mut buf = BufWriter::new(&mut f);
//     let write_result = write_layout(&mut buf, &layout, &WriterConfig::default());
//
//     dbg!(&write_result);
//     assert!(write_result.is_ok());
// }

/// Create a layout containing some paths, write it to the OASIS format, read it back and check that the result is correct.
#[test]
fn test_write_read_path() {
    use libreda_db::prelude::*;

    let mut layout = Layout::new();
    let layer = layout.find_or_create_layer(1, 0);
    let top_cell = layout.create_and_get_cell(Some("TOP"));

    // Add path to the top cell.
    let shapes = top_cell.shapes_get_or_create(layer);
    shapes.insert(Path::new_extended(vec![(0, 0), (1, 1)], 4, 3, 7));


    let mut buffer = Vec::new();
    OASISStreamWriter::default().
        write_layout(&mut buffer, &layout).unwrap();

    let mut layout2 = Layout::new();
    OASISStreamReader::default().
        read_layout(&mut buffer[..].as_ref(), &mut layout2).unwrap();

    let paths2: Vec<_> = layout2.cell_by_name("TOP").unwrap()
        .each_shape(layer)
        .map(|s| s.geometry.clone())
        .collect();

    let paths1: Vec<_> = layout.cell_by_name("TOP").unwrap()
        .each_shape(layer)
        .map(|s| s.geometry.clone())
        .collect();

    assert_eq!(paths2, paths1);
}