libreda_oasis/
reader.rs

1// Copyright (c) 2018-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Defines functions to parse an OASIS data stream and populate a `Layout`.
7//!
8//! OASIS BNF Syntax:
9//!
10//! ```txt
11//! <oasis-file>: <magic-bytes> START { CBLOCK | PAD | PROPERTY | <cell> | <name> }* END
12//! <name>: { CELLNAME | TEXTSTRING | LAYERNAME | PROPNAME | PROPSTRING | XNAME }
13//! <cell>: { CELL { CBLOCK | PAD | PROPERTY | XYRELATIVE | XYABSOLUTE | <element> }* }
14//! <element>: { <geometry> | PLACEMENT | TEXT | XELEMENT }
15//! <geometry>: { RECTANGLE | POLYGON | PATH | TRAPEZOID | CTRAPEZOID | CIRCLE | XGEOMETRY }
16//! ```
17
18use num_traits::Zero;
19
20use db::layout::prelude::*;
21use libreda_db as db;
22
23use byteorder::{LittleEndian, ReadBytesExt};
24use std::io::{Cursor, Read};
25
26use fnv::{FnvHashMap as HashMap, FnvHashSet as HashSet};
27
28use crate::base_types::RegularRepetition;
29use crate::base_types::Repetition;
30use crate::base_types::*;
31use crate::{Modal, NameOrRef, XYMode};
32
33#[derive(Debug, Clone)]
34enum PropertyParent<CellId: Clone, ShapeId: Clone, CellInstId: Clone> {
35    None,
36    Cell(CellId),
37    CellName(String),
38    Geometry(Vec<ShapeId>),
39    Placement(Vec<CellInstId>),
40    XElement,
41    XGeometry,
42}
43
44/// TODO
45fn read_offset_table<R: Read>(reader: &mut R) -> Result<(), OASISReadError> {
46    // For now this data is ignored.
47    let _cellname_flag = read_unsigned_integer(reader)?;
48    let _cellname_offset = read_unsigned_integer(reader)?;
49    let _textstring_flag = read_unsigned_integer(reader)?;
50    let _textstring_offset = read_unsigned_integer(reader)?;
51    let _propname_flag = read_unsigned_integer(reader)?;
52    let _propname_offset = read_unsigned_integer(reader)?;
53    let _propstring_flag = read_unsigned_integer(reader)?;
54    let _propstring_offset = read_unsigned_integer(reader)?;
55    let _layername_flag = read_unsigned_integer(reader)?;
56    let _layername_offset = read_unsigned_integer(reader)?;
57    let _xname_flag = read_unsigned_integer(reader)?;
58    let _xname_offset = read_unsigned_integer(reader)?;
59
60    Ok(())
61}
62
63/// TODO
64fn _read_properties<R: Read>(_reader: &mut R) -> Result<(), OASISReadError> {
65    unimplemented!()
66}
67
68/// Read a `Repetition` if it is present, otherwise take it from the modal variables.
69fn read_repetition_conditional<R: Read>(
70    reader: &mut R,
71    is_present: bool,
72    modal_value: &mut Option<Repetition>,
73) -> Result<Repetition, OASISReadError> {
74    // Construct positions from a repetition if there is any.
75    if is_present {
76        let repetition = read_repetition(reader)?;
77
78        // Get previous repetition if necessary.
79        let repetition = match repetition {
80            Repetition::ReusePrevious => modal_value
81                .as_ref()
82                .cloned()
83                .ok_or(OASISReadError::ModalRepetitionNotDefined)?,
84            _ => repetition,
85        };
86
87        assert_ne!(
88            &repetition,
89            &Repetition::ReusePrevious,
90            "`modal.repetition` should never be set to `ReusePrevious`."
91        );
92
93        *modal_value = Some(repetition.clone()); // Remember the last repetition.
94
95        Ok(repetition)
96    } else {
97        // Return single-element repetition.
98        Ok(Repetition::Regular(RegularRepetition::new(
99            Vector::zero(),
100            Vector::zero(),
101            1,
102            1,
103        )))
104    }
105}
106
107/// Convert a repetition into explicit displacements.
108fn repetition_to_offsets(rep: &Repetition, first_position: Vector<SInt>) -> Vec<Vector<SInt>> {
109    match &rep {
110        Repetition::ReusePrevious => {
111            unreachable!("`modal.repetition` should never be set to `ReusePrevious`.")
112        }
113        Repetition::Regular(r) => r.iter().map(|offset| first_position + offset).collect(),
114        Repetition::Irregular(r) => r.iter().map(|offset| first_position + *offset).collect(),
115    }
116}
117
118/// Read a x/y coordinate if it is explicitly defined, otherwise use the modal variable.
119/// Relative coordinates are resolved to absolute coordinates.
120/// The `modal_value` is used if the coordinate is not present.
121/// The `modal_value` is updated to the current coordinate value.
122fn read_coordinate_conditional<R: Read>(
123    reader: &mut R,
124    is_present: bool,
125    xy_mode: XYMode,
126    modal_value: &mut SInt,
127) -> Result<SInt, OASISReadError> {
128    let c = if is_present {
129        let c = read_signed_integer(reader)?;
130        match xy_mode {
131            XYMode::Absolute => c,
132            XYMode::Relative => *modal_value + c,
133        }
134    } else {
135        *modal_value
136    };
137    *modal_value = c;
138    Ok(c)
139}
140
141/// Read a (layer, datatype) pair.
142fn read_layernum_datatype<R: Read, C>(
143    reader: &mut R,
144    is_layer_present: bool,
145    is_datatype_present: bool,
146    modal: &mut Modal<C>,
147) -> Result<(UInt, UInt), OASISReadError> {
148    let layer = if is_layer_present {
149        read_unsigned_integer(reader)?
150    } else {
151        modal.layer.ok_or(OASISReadError::NoImplicitLayerDefined)?
152    };
153    modal.layer = Some(layer);
154
155    let datatype = if is_datatype_present {
156        read_unsigned_integer(reader)?
157    } else {
158        modal
159            .datatype
160            .ok_or(OASISReadError::NoImplicitDataTypeDefined)?
161    };
162    modal.datatype = Some(datatype);
163
164    Ok((layer, datatype))
165}
166
167/// Tells if IDs are given implicitly by a counter or are explicitly written in the file.
168#[derive(Eq, PartialEq, Debug)]
169enum IdMode {
170    /// ID mode is not known yet.
171    Any,
172    /// IDs are given based on a counter.
173    Impl,
174    /// IDs are given explicitely.
175    Expl,
176}
177
178impl Default for IdMode {
179    fn default() -> Self {
180        Self::Any
181    }
182}
183
184/// Collection of mutable state variables used in the OASIS reader/writer.
185#[derive(Debug)]
186struct ReaderState<L: LayoutBase> {
187    modal: Modal<L::CellId>,
188    table_offsets_at_start: bool,
189    offset_table: (),
190
191    m_expect_strict_mode: bool,
192    m_table_cell_name: Option<UInt>,
193
194    id_counters: IdCounters,
195
196    /// Mapping from cell IDs to cell names.
197    m_cell_names: HashMap<UInt, String>,
198    /// Remember the reference numbers of cell names that have been used as a forward reference
199    /// where the name string was not known yet. The corresponding cell needs to be updated
200    /// with the name once the cell name string is found.
201    m_cell_names_forward_references: HashMap<UInt, L::CellId>,
202    /// Unresolved property name forward references.
203    /// Mapping from property name reference to property parents with value list.
204    m_property_name_forward_references: HashMap<
205        UInt,
206        Vec<(
207            PropertyParent<L::CellId, L::ShapeId, L::CellInstId>,
208            Vec<PropertyValue>,
209        )>,
210    >,
211    /// Mapping from property IDs to property names.
212    m_propnames: HashMap<UInt, String>,
213    /// Mapping from property string IDs to property strings.
214    m_propstrings: HashMap<UInt, Vec<u8>>,
215    /// Mapping from text string IDs to text strings.
216    m_textstrings: HashMap<UInt, String>,
217
218    /// The cell currently under construction.
219    current_cell: Option<L::CellId>,
220    /// Counter for generating temporary cell names if they are not yet defined.
221    cell_name_counter: IdCounter,
222
223    /// Remember cells that have been created as forward references in placement records.
224    /// They must be respected when afterwards a CELL record creates a cell with the same name.
225    // TODO: This is not correctly used yet.
226    // TODO: Put this into the mutable state struct.
227    placement_cell_forward_references: HashSet<L::CellId>,
228
229    /// Remember with what to associate PROPERTY records.
230    property_parent: PropertyParent<L::CellId, L::ShapeId, L::CellInstId>,
231
232    /// Set to `true` while reading uncompressed data of a CBLOCK.
233    /// Used to detect nested CBLOCKs.
234    is_in_cblock: bool,
235}
236
237impl<L: LayoutBase> Default for ReaderState<L> {
238    fn default() -> Self {
239        Self {
240            modal: Default::default(),
241            table_offsets_at_start: false,
242            offset_table: Default::default(),
243            m_expect_strict_mode: false,
244            m_table_cell_name: Default::default(),
245            id_counters: Default::default(),
246            m_cell_names: Default::default(),
247            m_cell_names_forward_references: Default::default(),
248            m_property_name_forward_references: Default::default(),
249            m_propnames: Default::default(),
250            m_propstrings: Default::default(),
251            m_textstrings: Default::default(),
252            current_cell: Default::default(),
253            cell_name_counter: Default::default(),
254            placement_cell_forward_references: Default::default(),
255            property_parent: PropertyParent::None,
256            is_in_cblock: false,
257        }
258    }
259}
260
261/// Counter for implicit IDs.
262#[derive(Debug, Default)]
263struct IdCounter {
264    id_mode: IdMode,
265    counter: u32,
266}
267
268impl IdCounter {
269    fn next(&mut self) -> u32 {
270        let c = self.counter;
271        self.counter += 1;
272        c
273    }
274}
275
276/// Counters for implicit IDs.
277#[derive(Debug, Default)]
278struct IdCounters {
279    cellname: IdCounter,
280    textstrings: IdCounter,
281    propname: IdCounter,
282    propstrings: IdCounter,
283}
284
285impl<L> ReaderState<L>
286where
287    L: LayoutEdit<Coord = SInt>,
288{
289    fn read_layout<R: Read>(
290        mut self,
291        reader: &mut R,
292        layout: &mut L,
293    ) -> Result<(), OASISReadError> {
294        read_magic(reader)?;
295
296        self.read_start_record(reader, layout)?;
297        self.read_body(reader, layout)?;
298
299        Ok(())
300    }
301
302    fn read_start_record<R: Read>(
303        &mut self,
304        reader: &mut R,
305        layout: &mut L,
306    ) -> Result<(), OASISReadError> {
307        let record_id = read_unsigned_integer(reader)?;
308
309        if record_id != 1 {
310            return Err(OASISReadError::UnexpectedRecord(record_id)); // START record expected.
311        }
312
313        let version_string = read_ascii_string(reader)?;
314
315        if !version_string.eq("1.0") {
316            return Err(OASISReadError::WrongVersionString); // Wrong version string.
317        }
318        let resolution = read_real(reader)?; // Grid steps per micron.
319
320        // If the resolution is negative, NaN or infinite return an error.
321        {
322            let r = resolution.to_f64();
323            if f64::is_sign_negative(r) || f64::is_infinite(r) || f64::is_nan(r) {
324                return Err(OASISReadError::InvalidResolution(resolution)); // Invalid resolution.
325            }
326        }
327
328        let dbu = match resolution.try_to_int() {
329            Some(r) if r > 0 => r as UInt,
330            _ => unreachable!("Resolution must be a positive non-zero integer."), // already checked above
331        };
332        assert!(dbu >= 1); // already checked above
333        layout.set_dbu(dbu as SInt);
334
335        // If the `offset_flag` is set to 0 then the table-offsets is stored in the START record.
336        // Otherwise it is stored in the END record.
337        let offset_flag = read_unsigned_integer(reader)?;
338        trace!("offset flag = {}", offset_flag);
339        self.table_offsets_at_start = offset_flag == 0;
340        if self.table_offsets_at_start {
341            // table-offsets is stored in START record.
342            self.offset_table = read_offset_table(reader)?;
343        }
344
345        Ok(())
346    }
347
348    /// Set properties of a certain object `property_parent`.
349    fn set_property(
350        layout: &mut L,
351        property_parent: &PropertyParent<L::CellId, L::ShapeId, L::CellInstId>,
352        property_name: &String,
353        property_values: &[PropertyValue],
354        // Mapping from property string references to property strings.
355        property_strings: &HashMap<UInt, Vec<u8>>,
356    ) {
357        // Convert property values to data base types.
358        let property_values: Vec<db::property_storage::PropertyValue> = property_values
359            .iter()
360            .map(|v| {
361                use db::property_storage::PropertyValue as PV;
362                match v {
363                    PropertyValue::SInt(v) => (*v).into(),
364                    PropertyValue::UInt(v) => (*v).into(),
365                    PropertyValue::Real(v) => match v {
366                        Real::IEEEFloat32(v) => PV::Float(*v as f64),
367                        Real::IEEEFloat64(v) => PV::Float(*v),
368                        Real::PositiveWholeNumber(v) => (*v).into(),
369                        Real::NegativeWholeNumber(v) => (0 - *v as i32).into(),
370                        x => {
371                            dbg!(&property_name, x);
372                            unimplemented!();
373                        }
374                    },
375                    PropertyValue::AString(s) => s.clone().into(),
376                    PropertyValue::NString(s) => s.clone().into(),
377                    PropertyValue::BString(s) => s.clone().into(),
378                    PropertyValue::NStringRef(propstring_id) => {
379                        // Fetch property string.
380                        let bstring = property_strings
381                            .get(propstring_id)
382                            .expect("AString forward references are not supported yet."); // TODO
383
384                        let s = bytes_to_name_string(bstring.clone())
385                            .expect("Failed to convert bytes to name string.");
386                        s.into()
387                    }
388                    PropertyValue::AStringRef(propstring_id) => {
389                        // Fetch property string.
390                        let bstring = property_strings
391                            .get(propstring_id)
392                            .expect("NString forward references are not supported yet."); // TODO
393
394                        let s = bytes_to_ascii_string(bstring.clone())
395                            .expect("Failed to convert bytes to ascii string.");
396                        s.into()
397                    }
398                    PropertyValue::BStringRef(propstring_id) => {
399                        // Fetch property string.
400                        let bstring = property_strings
401                            .get(propstring_id)
402                            .expect("BString forward references are not supported yet."); // TODO
403                        bstring.clone().into()
404                    }
405                }
406            })
407            .collect();
408        let property_name: L::NameType = property_name.clone().into();
409        match &property_parent {
410            PropertyParent::None => {
411                // Properties related to the whole layout.
412                for v in &property_values {
413                    layout.set_chip_property(property_name.clone(), v.clone());
414                }
415            }
416            PropertyParent::Geometry(shapes) => {
417                for shape in shapes {
418                    for v in &property_values {
419                        layout.set_shape_property(shape, property_name.clone(), v.clone());
420                    }
421                }
422            }
423            PropertyParent::Cell(cell) => {
424                for v in &property_values {
425                    layout.set_cell_property(cell, property_name.clone(), v.clone());
426                }
427            }
428            PropertyParent::CellName(cell_name) => {
429                // Properties associated with a cell name.
430                let cell = layout
431                    .cell_by_name(cell_name)
432                    .expect("Cell name not found.");
433                for v in &property_values {
434                    layout.set_cell_property(&cell, property_name.clone(), v.clone());
435                }
436            }
437            PropertyParent::Placement(instances) => {
438                for instance in instances {
439                    for v in &property_values {
440                        layout.set_cell_instance_property(
441                            instance,
442                            property_name.clone(),
443                            v.clone(),
444                        );
445                    }
446                }
447            }
448            PropertyParent::XElement => {
449                warn!("Storing properties for XElement is not supported yet.");
450            }
451            PropertyParent::XGeometry => {
452                warn!("Storing properties for XGeometry is not supported yet.");
453            }
454        }
455    }
456
457    /// Generate a new cell name for cases when the name is not yet specified.
458    fn new_cell_name(&mut self) -> L::NameType {
459        format!("$${}$$", self.cell_name_counter.next()).into()
460    }
461
462    fn read_body<R: Read>(&mut self, reader: &mut R, layout: &mut L) -> Result<(), OASISReadError> {
463        loop {
464            let record_id = match read_unsigned_integer(reader) {
465                Ok(id) => id,
466                Err(e) => match e {
467                    OASISReadError::UnexpectedEndOfFile if self.is_in_cblock => {
468                        // TODO: This is not quite correct.
469                        // If a partial record ID can be read, then the error should be passed to the caller.
470                        break;
471                    }
472                    other => return Err(other),
473                },
474            };
475
476            trace!("record_id = {}", record_id);
477
478            match record_id {
479                0 => {
480                    // PAD record
481                }
482                1 => {
483                    // START record
484                    trace!("START record");
485                    return Err(OASISReadError::UnexpectedRecord(record_id)); // No start record expected.
486                }
487                2 => {
488                    self.read_end_record(reader)?;
489                    break;
490                }
491                3 | 4 => self.read_cell_name(reader, layout, record_id)?,
492                5 | 6 => {
493                    // TEXTSTRING record, associates a text string with a unique reference number.
494                    trace!("TEXTSTRING record");
495                    let textstring = read_ascii_string(reader)?;
496
497                    let id = if record_id == 5 {
498                        // Implicit IDs.
499                        if self.id_counters.textstrings.id_mode == IdMode::Expl {
500                            return Err(OASISReadError::MixedImplExplTextstringModes);
501                            // Implicit and explicit TEXTSTRING modes cannot be mixed.
502                        };
503                        self.id_counters.textstrings.id_mode = IdMode::Impl; // Remember mode.
504                        self.id_counters.textstrings.next()
505                    } else {
506                        // Explicit IDs.
507                        if self.id_counters.textstrings.id_mode == IdMode::Impl {
508                            return Err(OASISReadError::MixedImplExplTextstringModes);
509                            // Implicit and explicit TEXTSTRING modes cannot be mixed.
510                        };
511                        self.id_counters.textstrings.id_mode = IdMode::Expl; // Remember mode.
512                        read_unsigned_integer(reader)?
513                    };
514
515                    // Store text string.
516                    if self.m_textstrings.insert(id, textstring).is_some() {
517                        return Err(OASISReadError::TextStringAlreadyPresent(id));
518                    }
519
520                    self.modal.reset();
521                }
522                7 | 8 => {
523                    // PROPNAME record, associates property name with a unique reference number.
524                    trace!("PROPNAME record");
525
526                    let property_name = read_name_string(reader)?;
527                    trace!("property_name = {}", &property_name);
528
529                    let prop_name_id = if record_id == 7 {
530                        // Implicit IDs.
531                        if self.id_counters.propname.id_mode == IdMode::Expl {
532                            return Err(OASISReadError::MixedImplExplPropnameModes);
533                            // Implicit and explicit CELLNAME modes cannot be mixed.
534                        };
535                        self.id_counters.propname.id_mode = IdMode::Impl; // Remember mode.
536                        self.id_counters.propname.next() // Infinite sequence, unwrap does not fail.
537                    } else {
538                        // Explicit IDs.
539                        if self.id_counters.propname.id_mode == IdMode::Impl {
540                            return Err(OASISReadError::MixedImplExplPropnameModes);
541                            // Implicit and explicit CELLNAME modes cannot be mixed.
542                        };
543                        self.id_counters.propname.id_mode = IdMode::Expl; // Remember mode.
544                        read_unsigned_integer(reader)?
545                    };
546                    trace!("prop_id = {}", prop_name_id);
547
548                    // TODO: Property forward references without property-string forward references could be resolved already.
549
550                    // Store property name by the reference number.
551                    if let Some(_existing_name) =
552                        self.m_propnames.insert(prop_name_id, property_name)
553                    {
554                        return Err(OASISReadError::PropnameIdAlreadyPresent(prop_name_id));
555                    }
556
557                    self.modal.reset();
558                }
559                9 | 10 => {
560                    // PROPSTRING record, associates a property string with a unique reference number.
561                    // The property string can be an a-string, b-string or n-string depending on the
562                    // referencing property record (28).
563                    trace!("PROPSTRING record");
564                    // `propstring` is a a-string, n-string or b-string depending on the referencing
565                    // PROPERTY record.
566                    let propstring = read_byte_string(reader)?;
567                    trace!("propstring = {:?}", &propstring);
568
569                    let id = if record_id == 9 {
570                        // Implicit IDs.
571                        if self.id_counters.propstrings.id_mode == IdMode::Expl {
572                            return Err(OASISReadError::MixedImplExplPropstringModes);
573                            // Implicit and explicit PROPSTRING modes cannot be mixed.
574                        };
575                        self.id_counters.propstrings.id_mode = IdMode::Impl; // Remember mode.
576                        self.id_counters.propstrings.next() // Infinite sequence, unwrap does not fail.
577                    } else {
578                        // Explicit IDs.
579                        if self.id_counters.propstrings.id_mode == IdMode::Impl {
580                            return Err(OASISReadError::MixedImplExplPropstringModes);
581                            // Implicit and explicit PROPSTRING modes cannot be mixed.
582                        };
583                        self.id_counters.propstrings.id_mode = IdMode::Expl; // Remember mode.
584                        read_unsigned_integer(reader)?
585                    };
586
587                    // Store text string.
588                    if let Some(_existing_name) = self.m_propstrings.insert(id, propstring) {
589                        // Conflict: Property string ID is already used.
590                        return Err(OASISReadError::PropStringAlreadyPresent(id));
591                    }
592
593                    self.modal.reset();
594                }
595                11 | 12 => {
596                    // LAYERNAME record
597                    trace!("LAYERNAME record");
598
599                    let layer_name = read_name_string(reader)?;
600                    trace!("layer_name = {}", &layer_name);
601
602                    let read_interval = |reader: &mut R| {
603                        let interval_type = read_unsigned_integer(reader)?;
604                        let max = UInt::MAX; // Maximum integer value. Used as a pseudo representation for infinity.
605                        match interval_type {
606                            0 => Ok((0, max)),
607                            1 => Ok((0, read_unsigned_integer(reader)?)),
608                            2 => Ok((read_unsigned_integer(reader)?, max)),
609                            3 => {
610                                let a = read_unsigned_integer(reader)?;
611                                Ok((a, a))
612                            }
613                            4 => Ok((
614                                read_unsigned_integer(reader)?,
615                                read_unsigned_integer(reader)?,
616                            )),
617                            t => Err(OASISReadError::IllegalIntervalType(t)), // Invalid interval type.
618                        }
619                    };
620
621                    let (layer_start, layer_end) = read_interval(reader)?;
622                    let (dtype_start, dtype_end) = read_interval(reader)?;
623
624                    // Set the layer name in the layout.
625                    let layer_name: L::NameType = layer_name.clone().into();
626                    for l in layer_start..layer_end {
627                        for d in dtype_start..dtype_end {
628                            let idx = layout.find_or_create_layer(l, d);
629                            layout.set_layer_name(&idx, Some(layer_name.clone()));
630                        }
631                    }
632
633                    // Reset modal variables.
634                    self.modal.reset();
635
636                    warn!("LAYERNAME record is not implemented: '{}'", &layer_name);
637                }
638                13 | 14 => {
639                    // 13: CELL record, with reference-number for the name.
640                    // 14: CELL record, with name string.
641                    trace!("CELL record");
642
643                    // All subsequent records in the file up to the next CELL, END, or <name> record
644                    // are considered to be part of that cell.
645
646                    let cell_name = if record_id == 13 {
647                        // Name by reference.
648                        let cell_name_reference = read_unsigned_integer(reader)?;
649                        let cell_name = self.m_cell_names.get(&cell_name_reference);
650
651                        // Return the name if it is present, other wise return the reference number.
652                        if let Some(cell_name) = cell_name {
653                            NameOrRef::Name(cell_name.clone())
654                        } else {
655                            NameOrRef::NameRef(cell_name_reference)
656                        }
657                    } else {
658                        NameOrRef::Name(read_name_string(reader)?)
659                    };
660                    trace!("cell_name = {:?}", &cell_name);
661
662                    // Set the cell name if it is already defined.
663                    // Otherwise remember the forward reference such that the name can be defined later.
664                    let cell_idx = match cell_name {
665                        NameOrRef::Name(n) => {
666                            if let Some(cell_idx) = layout.cell_by_name(&n) {
667                                // Cell with this name already exists.
668                                // This is fine if it has been created as a forward reference for a placement record.
669                                // Check if it is a forward reference to a placement record.
670                                if self.placement_cell_forward_references.remove(&cell_idx) {
671                                    // Cell has been created as a forward reference. No name clash.
672                                    cell_idx
673                                } else {
674                                    // Cell has not been created as a forward reference. Name clash.
675                                    return Err(OASISReadError::CellnameAlreadyPresent(n));
676                                }
677                            } else {
678                                layout.create_cell(n.into())
679                            }
680                        }
681                        NameOrRef::NameRef(r) => {
682                            // Check if the reference does not already exist.
683                            if let Some(cell_idx) = self.m_cell_names_forward_references.get(&r) {
684                                if self.placement_cell_forward_references.remove(cell_idx) {
685                                    // Cell has been created as a forward reference. No name reference clash.
686                                    cell_idx.clone()
687                                } else {
688                                    // Cell has not been created as a forward reference. Name reference clash.
689                                    return Err(OASISReadError::CellnameIdAlreadyPresent(r));
690                                }
691                            } else {
692                                // The value of this reference has not yet been defined. Generate a temporary name.
693                                let cell_idx = layout.create_cell(self.new_cell_name());
694                                // Remember the forward reference.
695                                self.m_cell_names_forward_references
696                                    .insert(r, cell_idx.clone());
697                                cell_idx
698                            }
699                        }
700                    };
701
702                    // Remember this cell as the 'active' cell.
703                    self.current_cell = Some(cell_idx.clone());
704
705                    // Associate following properties with this cell for now.
706                    self.property_parent = PropertyParent::Cell(cell_idx);
707
708                    // Reset modal values.
709                    self.modal.reset();
710                }
711                15 => {
712                    // XYABSOLUTE record
713                    trace!("XYABSOLUTE record");
714                    self.modal.xy_mode = XYMode::Absolute;
715                }
716                16 => {
717                    // XYRELATIVE record
718                    trace!("XYRELATIVE record");
719                    self.modal.xy_mode = XYMode::Relative;
720                }
721                17 | 18 => {
722                    // PLACEMENT record
723                    // 17/18 are different in how the magnification and rotation are encoded.
724                    trace!("PLACEMENT record");
725
726                    let placement_info_byte = read_byte(reader)?;
727                    let b = |index| (placement_info_byte >> index) & 1u8 == 1u8;
728                    let is_cell_reference_explicit = b(7); // C
729                    let is_cell_reference_number_present = b(6); // N
730                    let is_x_present = b(5); // X
731                    let is_y_present = b(4); // Y
732                    let is_repetition_present = b(3); // R
733                    let is_flip = b(0); // F
734
735                    // Get either a reference to the cell to be instantiated or at least the name to it.
736                    // It is possible that this is a forward reference with the cell not yet defined.
737                    let instance_ref = if is_cell_reference_explicit {
738                        // Read cell name.
739                        let cell_name = if is_cell_reference_number_present {
740                            // Cell name is given by reference number.
741                            let cell_name_ref = read_unsigned_integer(reader)?;
742
743                            // Get cell name if it is already defined.
744                            if let Some(cell_name) = self.m_cell_names.get(&cell_name_ref) {
745                                NameOrRef::Name(cell_name.clone())
746                            } else {
747                                NameOrRef::NameRef(cell_name_ref)
748                            }
749                        } else {
750                            // Read explicit cell name.
751                            NameOrRef::Name(read_name_string(reader)?)
752                        };
753
754                        // Get the cell by the name or create it if necessary.
755                        // If the cell needs to be created but no name is defined yet
756                        // an unnamed cell will be created.
757                        // TODO: FIXME: What if a cell is placed once by name and once by reference before it is created and before the name is defined?
758                        // "Use of a reference-number for which there is no corresponding CELLNAME
759                        // record should be treated as a fatal error"
760                        match cell_name {
761                            NameOrRef::Name(n) => {
762                                if let Some(cell) = layout.cell_by_name(&n) {
763                                    cell
764                                } else {
765                                    let cell = layout.create_cell(n.into());
766                                    // Remember that this cell has been created as a forward reference.
767                                    self.placement_cell_forward_references.insert(cell.clone());
768                                    cell
769                                }
770                            }
771                            NameOrRef::NameRef(r) => {
772                                // Try to find the cell by forward reference (if the name is not yet defined).
773                                self.m_cell_names_forward_references
774                                    .get(&r)
775                                    .cloned()
776                                    // If no forward reference can be found, create a new cell
777                                    // and a new forward reference.
778                                    .unwrap_or_else(|| {
779                                        // Create an unnamed cell.
780                                        let cell = layout.create_cell(self.new_cell_name());
781                                        self.m_cell_names_forward_references
782                                            .insert(r, cell.clone());
783                                        // Remember that this cell has been created as a forward reference.
784                                        self.placement_cell_forward_references.insert(cell.clone());
785                                        cell
786                                    })
787                            }
788                        }
789                    } else {
790                        // Implicit cell.
791                        // Use modal variable `placement_cell` which refers to the same cell as the placement record before.
792                        self.modal
793                            .placement_cell
794                            .clone()
795                            .ok_or(OASISReadError::ModalPlacementCellNotDefined)?
796                    };
797
798                    // Remember the last placement cell if any.
799                    self.modal.placement_cell = Some(instance_ref.clone());
800
801                    // Read magnification and angle or take default values.
802                    let (magnification, angle_degrees) = if record_id == 17 {
803                        let aa = (placement_info_byte >> 1) & 3u8; // AA
804                        let angle_degrees = 90 * (aa as u16);
805                        let magnification = 1;
806                        (
807                            Real::PositiveWholeNumber(magnification),
808                            Real::PositiveWholeNumber(angle_degrees.into()),
809                        )
810                    } else {
811                        // Magnification and rotation are reals.
812                        let is_magnification_present = b(2); // M
813                        let is_angle_present = b(1); // A
814                                                     // Read magnification and angle (default are 1.0 and 0.0).
815                        let magnification = if is_magnification_present {
816                            read_real(reader)?
817                        } else {
818                            Real::PositiveWholeNumber(1)
819                        };
820
821                        // Read rotation angle default is 0.
822                        let angle_degrees = if is_angle_present {
823                            read_real(reader)?
824                        } else {
825                            Real::PositiveWholeNumber(0)
826                        };
827
828                        (magnification, angle_degrees)
829                    };
830
831                    // Read x.
832                    let x = read_coordinate_conditional(
833                        reader,
834                        is_x_present,
835                        self.modal.xy_mode,
836                        &mut self.modal.placement_x,
837                    )?;
838
839                    // Read y.
840                    let y = read_coordinate_conditional(
841                        reader,
842                        is_y_present,
843                        self.modal.xy_mode,
844                        &mut self.modal.placement_y,
845                    )?;
846
847                    // Construct placement offset.
848                    let displacement = Vector::new(x, y);
849
850                    // Construct positions from a repetition if there is any.
851                    let repetition = read_repetition_conditional(
852                        reader,
853                        is_repetition_present,
854                        &mut self.modal.repetition,
855                    )?;
856
857                    // Convert angle back into a multiple of 90 degrees if possible.
858                    let angle90 = match angle_degrees.try_to_int() {
859                        Some(0) => Some(Angle::R0),
860                        Some(90) => Some(Angle::R90),
861                        Some(180) => Some(Angle::R180),
862                        Some(270) => Some(Angle::R270),
863                        _ => None,
864                    }
865                    .expect("Rotation angle must be a multiple of 90 degree."); // TODO: Support complex transforms here.
866
867                    // TODO: Support non-integer magnification.
868                    let magnification = magnification
869                        .try_to_int()
870                        .expect("Magnification mut be an integer.");
871
872                    // Convert the repetition into actual offsets.
873                    let positions = repetition_to_offsets(&repetition, displacement);
874
875                    // Create cell instances.
876                    // TODO: Create cell instance arrays.
877                    let parent_cell = self
878                        .current_cell
879                        .as_ref()
880                        .ok_or(OASISReadError::NoCellRecordPresent)?;
881
882                    let mut instances = Vec::with_capacity(positions.len());
883                    for pos in positions {
884                        let trans = SimpleTransform::new(is_flip, angle90, magnification, pos);
885                        let inst = layout.create_cell_instance(parent_cell, &instance_ref, None);
886                        layout.set_transform(&inst, trans);
887                        instances.push(inst);
888                    }
889
890                    // Associate following properties with this instance for now.
891                    self.property_parent = PropertyParent::Placement(instances);
892                }
893                19 => {
894                    // TEXT record
895                    trace!("TEXT record");
896
897                    let text_info_byte = read_byte(reader)?;
898                    let b = |index| (text_info_byte >> index) & 1u8 == 1u8;
899                    let is_text_reference_explicit = b(6); // C
900
901                    let text_string = if is_text_reference_explicit {
902                        let reference_number_present = b(5);
903                        if reference_number_present {
904                            let ref_number = read_unsigned_integer(reader)?;
905                            let text_string = self.m_textstrings.get(&ref_number);
906                            text_string
907                                .cloned()
908                                .ok_or(OASISReadError::PropStringIdNotFound(ref_number))?
909                        } else {
910                            read_ascii_string(reader)?
911                        }
912                    } else {
913                        self.modal
914                            .text_string
915                            .as_ref()
916                            .cloned()
917                            .ok_or(OASISReadError::NoImplicitTextStringDefined)?
918                    };
919                    trace!("text_string = {}", &text_string);
920                    self.modal.text_string = Some(text_string.clone());
921
922                    let is_explicit_textlayer = b(0);
923                    let is_explicit_texttype = b(1);
924                    let is_repetition_present = b(2);
925                    let is_x_present = b(4);
926                    let is_y_present = b(3);
927
928                    let textlayer = if is_explicit_textlayer {
929                        read_unsigned_integer(reader)?
930                    } else {
931                        self.modal
932                            .textlayer
933                            .ok_or(OASISReadError::ModalTextLayerDefined)?
934                    };
935                    self.modal.textlayer = Some(textlayer);
936
937                    let texttype = if is_explicit_texttype {
938                        read_unsigned_integer(reader)?
939                    } else {
940                        self.modal
941                            .texttype
942                            .ok_or(OASISReadError::ModalTextTypeDefined)?
943                    };
944                    self.modal.texttype = Some(texttype);
945
946                    // Read x.
947                    let x = read_coordinate_conditional(
948                        reader,
949                        is_x_present,
950                        self.modal.xy_mode,
951                        &mut self.modal.text_x,
952                    )?;
953
954                    // Read y.
955                    let y = read_coordinate_conditional(
956                        reader,
957                        is_y_present,
958                        self.modal.xy_mode,
959                        &mut self.modal.text_y,
960                    )?;
961
962                    // Construct the coordinate of the first text instance (there might be a repetition).
963                    let pos = Vector::new(x, y);
964
965                    // Construct positions from a repetition if there is any.
966                    let repetition = read_repetition_conditional(
967                        reader,
968                        is_repetition_present,
969                        &mut self.modal.repetition,
970                    )?;
971                    let positions = repetition_to_offsets(&repetition, pos);
972
973                    let parent_cell = self
974                        .current_cell
975                        .as_ref()
976                        .ok_or(OASISReadError::NoCellRecordPresent)?;
977                    let layer_id = layout.find_or_create_layer(textlayer, texttype);
978
979                    let mut shape_instances = Vec::with_capacity(positions.len());
980
981                    // Create text instances.
982                    // TODO: Use L::NameType for strings. They might be cheaper to clone than `String`.
983                    itertools::repeat_n(text_string, positions.len()) // Avoid cloning for the last instance.
984                        .zip(positions)
985                        .for_each(|(text_string, pos)| {
986                            let text = Text::new(text_string, pos.into());
987                            let shape_id = layout.insert_shape(parent_cell, &layer_id, text.into());
988                            shape_instances.push(shape_id); // Remember all instances.
989                        });
990
991                    // Remember the shapes to associate upcoming properties with them.
992                    self.property_parent = PropertyParent::Geometry(shape_instances);
993                }
994                20 => {
995                    // RECTANGLE record.
996                    trace!("RECTANGLE record");
997
998                    let rectangle_info_byte = read_byte(reader)?;
999                    let b = |index| (rectangle_info_byte >> index) & 1u8 == 1u8;
1000
1001                    let is_layer_number_present = b(0);
1002                    let is_datatype_number_present = b(1);
1003                    let is_width_present = b(6); // W
1004                    let is_height_present = b(5); // H
1005                    let is_x_present = b(4); // X
1006                    let is_y_present = b(3); // Y
1007                    let is_repetition_present = b(2); // R
1008                    let is_square = b(7); // S
1009
1010                    let (layer, datatype) = read_layernum_datatype(
1011                        reader,
1012                        is_layer_number_present,
1013                        is_datatype_number_present,
1014                        &mut self.modal,
1015                    )?;
1016
1017                    let width = if is_width_present {
1018                        read_unsigned_integer(reader)?
1019                    } else {
1020                        self.modal
1021                            .geometry_w
1022                            .ok_or(OASISReadError::ModalGeometryWNotDefined)?
1023                    };
1024                    self.modal.geometry_w = Some(width);
1025
1026                    let height = if is_square {
1027                        if is_height_present {
1028                            // `height` should not be present if S is 1.
1029                            return Err(OASISReadError::HeightIsPresentForSquare);
1030                        } else {
1031                            width
1032                        }
1033                    } else if is_height_present {
1034                        read_unsigned_integer(reader)?
1035                    } else {
1036                        self.modal
1037                            .geometry_h
1038                            .ok_or(OASISReadError::ModalGeometryHNotDefined)?
1039                    };
1040                    self.modal.geometry_h = Some(height);
1041
1042                    // Read x.
1043                    let x = read_coordinate_conditional(
1044                        reader,
1045                        is_x_present,
1046                        self.modal.xy_mode,
1047                        &mut self.modal.geometry_x,
1048                    )?;
1049
1050                    // Read y.
1051                    let y = read_coordinate_conditional(
1052                        reader,
1053                        is_y_present,
1054                        self.modal.xy_mode,
1055                        &mut self.modal.geometry_y,
1056                    )?;
1057
1058                    // Construct the coordinate of the first text instance (there might be a repetition).
1059                    let pos = Vector::new(x, y);
1060
1061                    // Construct positions from a repetition if there is any.
1062                    let repetition = read_repetition_conditional(
1063                        reader,
1064                        is_repetition_present,
1065                        &mut self.modal.repetition,
1066                    )?;
1067
1068                    let positions = repetition_to_offsets(&repetition, pos);
1069
1070                    let diagonal = Vector::new(width as SInt, height as SInt);
1071
1072                    let lower_left = Point::zero();
1073                    let rect = Rect::new(lower_left, lower_left + diagonal);
1074
1075                    if let Some(parent_cell) = &self.current_cell {
1076                        let layer_id = layout.find_or_create_layer(layer, datatype);
1077
1078                        let mut shape_instances = Vec::new();
1079                        // Create rectangle instances.
1080                        for pos in positions {
1081                            let r = Rect::new(rect.lower_left() + pos, rect.upper_right() + pos);
1082                            let shape_id = layout.insert_shape(parent_cell, &layer_id, r.into());
1083                            shape_instances.push(shape_id); // Remember all instances.
1084                        }
1085
1086                        // Remember the shapes to associate upcoming properties with them.
1087                        self.property_parent = PropertyParent::Geometry(shape_instances);
1088                    } else {
1089                        return Err(OASISReadError::NoCellRecordPresent);
1090                    }
1091                }
1092                21 => {
1093                    // POLYGON record.
1094                    trace!("POLYGON record");
1095
1096                    let polygon_info_byte = read_byte(reader)?;
1097                    let b = |index| (polygon_info_byte >> index) & 1u8 == 1u8;
1098
1099                    let is_layer_number_present = b(0); // L
1100                    let is_datatype_number_present = b(1); // D
1101                    let is_repetition_present = b(2); // R
1102                    let is_y_present = b(3); // Y
1103                    let is_x_present = b(4); // X
1104                    let is_pointlist_present = b(5); // P
1105
1106                    let (layer, datatype) = read_layernum_datatype(
1107                        reader,
1108                        is_layer_number_present,
1109                        is_datatype_number_present,
1110                        &mut self.modal,
1111                    )?;
1112
1113                    if is_pointlist_present {
1114                        let p = read_point_list(reader)?;
1115                        self.modal.polygon_point_list = Some(p);
1116                    }
1117
1118                    // Read x.
1119                    let x = read_coordinate_conditional(
1120                        reader,
1121                        is_x_present,
1122                        self.modal.xy_mode,
1123                        &mut self.modal.geometry_x,
1124                    )?;
1125
1126                    // Read y.
1127                    let y = read_coordinate_conditional(
1128                        reader,
1129                        is_y_present,
1130                        self.modal.xy_mode,
1131                        &mut self.modal.geometry_y,
1132                    )?;
1133
1134                    let point0 = Vector::new(x, y);
1135
1136                    // Create coordinates.
1137                    let points: Vec<_> = self
1138                        .modal
1139                        .polygon_point_list
1140                        .as_ref()
1141                        .ok_or(OASISReadError::ModalPolygonPointListNotDefined)
1142                        .map(|pointlist| pointlist.points(Vector::zero(), true))?;
1143
1144                    // Construct positions from a repetition if there is any.
1145                    let repetition = read_repetition_conditional(
1146                        reader,
1147                        is_repetition_present,
1148                        &mut self.modal.repetition,
1149                    )?;
1150                    let positions = repetition_to_offsets(&repetition, point0);
1151
1152                    let polygon = SimplePolygon::new(points).normalized_orientation::<i64>();
1153
1154                    if let Some(parent_cell) = &self.current_cell {
1155                        let layer_id = layout.find_or_create_layer(layer, datatype);
1156
1157                        // Repeat polygon and add the repetitions to the current cell.
1158                        let mut shape_instances = Vec::with_capacity(positions.len());
1159
1160                        // Create polygon instances.
1161                        itertools::repeat_n(polygon, positions.len()) // Avoid cloning for the last instance.
1162                            .zip(positions)
1163                            .for_each(|(mut polygon, pos)| {
1164                                // Translate the polygon to the position.
1165                                // This is a hack around the implementation of `polygon.translate()` which unnecessarily normalizes the polygon orientation.
1166                                polygon.with_points_mut(|points| {
1167                                    points.iter_mut().for_each(|point| *point += pos)
1168                                });
1169
1170                                let shape_id =
1171                                    layout.insert_shape(parent_cell, &layer_id, polygon.into());
1172                                shape_instances.push(shape_id); // Remember all instances.
1173                            });
1174
1175                        // Remember the shapes to associate upcoming properties with them.
1176                        self.property_parent = PropertyParent::Geometry(shape_instances);
1177                    } else {
1178                        return Err(OASISReadError::NoCellRecordPresent);
1179                    }
1180                }
1181                22 => {
1182                    // PATH record.
1183                    trace!("PATH record");
1184
1185                    let path_info_byte = read_byte(reader)?;
1186                    let b = |index| (path_info_byte >> index) & 1u8 == 1u8;
1187
1188                    let is_layer_number_present = b(0); // L
1189                    let is_datatype_number_present = b(1); // D
1190                    let is_repetition_present = b(2); // R
1191                    let is_y_present = b(3); // Y
1192                    let is_x_present = b(4); // X
1193                    let is_pointlist_present = b(5); // P
1194                    let is_half_width_present = b(6); // W
1195                    let is_extension_scheme_present = b(7); // E
1196
1197                    let (layer, datatype) = read_layernum_datatype(
1198                        reader,
1199                        is_layer_number_present,
1200                        is_datatype_number_present,
1201                        &mut self.modal,
1202                    )?;
1203
1204                    let half_width = if is_half_width_present {
1205                        let hw = read_unsigned_integer(reader)?;
1206                        self.modal.path_halfwidth = Some(hw);
1207                        hw
1208                    } else {
1209                        self.modal
1210                            .path_halfwidth
1211                            .ok_or(OASISReadError::ModalPathHalfWidthNotDefined)?
1212                    };
1213
1214                    let (start_ext, end_ext) = if is_extension_scheme_present {
1215                        let ext_scheme = read_unsigned_integer(reader)?;
1216                        let ss = (ext_scheme >> 2) & 0b11; // Path start extension.
1217                        let ee = ext_scheme & 0b11; // Path end extension.
1218
1219                        let start_ext = match ss {
1220                            0 => self
1221                                .modal
1222                                .path_start_extension
1223                                .ok_or(OASISReadError::ModalPathStartExtensionNotDefined)?,
1224                            1 => 0, // 'Flush'
1225                            2 => half_width as SInt,
1226                            3 => read_signed_integer(reader)?,
1227                            _ => unreachable!(), // This cannot happen.
1228                        };
1229                        let end_ext = match ee {
1230                            0 => self
1231                                .modal
1232                                .path_end_extension
1233                                .ok_or(OASISReadError::ModalPathEndExtensionNotDefined)?,
1234                            1 => 0, // 'Flush'
1235                            2 => half_width as SInt,
1236                            3 => read_signed_integer(reader)?,
1237                            _ => unreachable!(), // This cannot happen.
1238                        };
1239
1240                        (start_ext, end_ext)
1241                    } else {
1242                        let s = self
1243                            .modal
1244                            .path_start_extension
1245                            .ok_or(OASISReadError::ModalPathStartExtensionNotDefined)?;
1246                        let e = self
1247                            .modal
1248                            .path_end_extension
1249                            .ok_or(OASISReadError::ModalPathEndExtensionNotDefined)?;
1250                        (s, e)
1251                    };
1252                    self.modal.path_start_extension = Some(start_ext);
1253                    self.modal.path_end_extension = Some(end_ext);
1254
1255                    if is_pointlist_present {
1256                        let p = read_point_list(reader)?;
1257                        self.modal.path_point_list = Some(p);
1258                    }
1259
1260                    // Read x and set modal geometry_x.
1261                    let x = read_coordinate_conditional(
1262                        reader,
1263                        is_x_present,
1264                        self.modal.xy_mode,
1265                        &mut self.modal.geometry_x,
1266                    )?;
1267
1268                    // Read y and set modal geometry_y.
1269                    let y = read_coordinate_conditional(
1270                        reader,
1271                        is_y_present,
1272                        self.modal.xy_mode,
1273                        &mut self.modal.geometry_y,
1274                    )?;
1275
1276                    let point0 = Vector::new(x, y);
1277
1278                    // Construct positions from a repetition if there is any.
1279                    let repetition = read_repetition_conditional(
1280                        reader,
1281                        is_repetition_present,
1282                        &mut self.modal.repetition,
1283                    )?;
1284                    let positions = repetition_to_offsets(&repetition, point0);
1285
1286                    // Create coordinates.
1287                    let points: Vec<_> = self
1288                        .modal
1289                        .path_point_list
1290                        .as_ref()
1291                        .ok_or(OASISReadError::ModalPathPointListNotDefined)
1292                        .map(|pointlist| pointlist.points(Vector::zero(), false))?;
1293
1294                    // Create untranslated path.
1295                    let path =
1296                        Path::new_extended(points, half_width as SInt * 2, start_ext, end_ext);
1297
1298                    if let Some(parent_cell) = &self.current_cell {
1299                        let layer_id = layout.find_or_create_layer(layer, datatype);
1300
1301                        // Repeat shape and add the repetitions to the current cell.
1302                        let mut shape_instances = Vec::with_capacity(positions.len());
1303                        // Create path instances.
1304                        itertools::repeat_n(path, positions.len()) // Avoid cloning for the last instance.
1305                            .zip(positions)
1306                            .for_each(|(mut path, pos)| {
1307                                // Translate the path in-place.
1308                                path.points.points.iter_mut().for_each(|p| *p += pos);
1309
1310                                let shape_id =
1311                                    layout.insert_shape(parent_cell, &layer_id, path.into());
1312                                shape_instances.push(shape_id); // Remember all instances.
1313                            });
1314
1315                        // Remember the shapes to associate upcoming properties with them.
1316                        self.property_parent = PropertyParent::Geometry(shape_instances);
1317                    } else {
1318                        return Err(OASISReadError::NoCellRecordPresent);
1319                    }
1320                }
1321                28 | 29 => self.read_property_record(reader, layout, record_id)?,
1322                30 | 31 => {
1323                    // XNAME record
1324                    trace!("XNAME record");
1325
1326                    let _xname_attribute = read_unsigned_integer(reader)?;
1327                    let _xname_string = read_byte_string(reader)?;
1328
1329                    if record_id == 31 {
1330                        let _reference_number = read_unsigned_integer(reader)?;
1331                    }
1332
1333                    self.modal.reset();
1334
1335                    // TODO: This is neither complete nor correct.
1336
1337                    unimplemented!("XNAME record is not supported yet.")
1338                }
1339                32 => {
1340                    // XELEMENT record
1341                    trace!("XELEMENT record");
1342
1343                    let _xelement_attribute = read_unsigned_integer(reader)?;
1344                    let _xelement_string = read_byte_string(reader)?; // Contains user defined data.
1345
1346                    self.property_parent = PropertyParent::XElement;
1347                }
1348                33 => {
1349                    // XGEOMETRY record
1350                    trace!("XGEOMETRY record");
1351
1352                    // TODO: This is neither complete nor correct.
1353
1354                    self.property_parent = PropertyParent::XGeometry;
1355
1356                    unimplemented!("XGEOMETRY record is not supported yet.")
1357                }
1358                34 => {
1359                    // CBLOCK
1360                    trace!("CBLOCK");
1361
1362                    if self.is_in_cblock {
1363                        log::error!("nested CBLOCK");
1364                        return Err(OASISReadError::NestedCblock);
1365                    }
1366
1367                    let compression_type = read_unsigned_integer(reader)?;
1368
1369                    if compression_type != 0 {
1370                        return Err(OASISReadError::UnsupportedCompressionType(compression_type));
1371                    }
1372
1373                    let uncompressed_byte_count = read_unsigned_integer(reader)? as usize;
1374                    let compressed_byte_count = read_unsigned_integer(reader)?;
1375
1376                    trace!("read compressed bytes: {} bytes", compressed_byte_count);
1377                    let mut compressed_bytes = vec![0; compressed_byte_count as usize];
1378                    reader.read_exact(&mut compressed_bytes)?;
1379
1380                    // TODO: Instead of copying data decompress directly on the stream as KLayout does.
1381                    // For example use flate2::read::DeflateDecoder.
1382                    trace!("deflate CBLOCK");
1383                    let mut decompressor = flate2::Decompress::new(false);
1384                    let mut uncompressed_bytes =
1385                        Vec::with_capacity(uncompressed_byte_count.min(1 << 20));
1386                    decompressor
1387                        .decompress_vec(
1388                            &compressed_bytes,
1389                            &mut uncompressed_bytes,
1390                            flate2::FlushDecompress::Finish,
1391                        )
1392                        .map_err(|_e| OASISReadError::DecompressError)?;
1393
1394                    // Announced and actual size of the uncompressed data must match.
1395                    if uncompressed_bytes.len() != uncompressed_byte_count {
1396                        return Err(OASISReadError::UncompressedByteCountMismatch(
1397                            uncompressed_byte_count,
1398                            uncompressed_bytes.len(),
1399                        ));
1400                    }
1401
1402                    self.is_in_cblock = true;
1403                    let result = self.read_body(&mut Cursor::new(uncompressed_bytes), layout);
1404                    self.is_in_cblock = false;
1405                    result?;
1406                }
1407                _ => {
1408                    return Err(OASISReadError::UnsupportedRecordType(record_id));
1409                }
1410            }
1411        }
1412
1413        // Resolve property forward references.
1414        // if let Some(forward_references) = self.m_property_name_forward_references.remove(&prop_name_id) {
1415        for (prop_name_id, forward_references) in self.m_property_name_forward_references.drain() {
1416            let property_name = self.m_propnames.get(&prop_name_id).unwrap();
1417            trace!(
1418                "Resolve {} forward references '{}=>{}'.",
1419                forward_references.len(),
1420                prop_name_id,
1421                &property_name
1422            );
1423
1424            for (property_parent, property_values) in forward_references {
1425                Self::set_property(
1426                    layout,
1427                    &property_parent,
1428                    property_name,
1429                    &property_values,
1430                    &self.m_propstrings,
1431                );
1432            }
1433        }
1434
1435        // Check for cells that never had their name defined.
1436        if !self.m_cell_names_forward_references.is_empty() {
1437            error!("Some cell name forward references where not resolved.");
1438            return Err(OASISReadError::UnresolvedForwardReferences(
1439                self.m_cell_names_forward_references
1440                    .keys()
1441                    .copied()
1442                    .collect(),
1443            ));
1444        }
1445
1446        debug_assert!(
1447            self.placement_cell_forward_references.is_empty(),
1448            "Some forward references have never been resolved."
1449        );
1450
1451        // Check that all property forward reference have been resolved.
1452        if !self.m_property_name_forward_references.is_empty() {
1453            error!("Some property name forward references where not resolved.");
1454            return Err(OASISReadError::UnresolvedForwardReferences(
1455                self.m_property_name_forward_references
1456                    .keys()
1457                    .copied()
1458                    .collect(),
1459            ));
1460        }
1461
1462        Ok(())
1463    }
1464
1465    fn read_end_record<R: Read>(&mut self, reader: &mut R) -> Result<(), OASISReadError> {
1466        // END record.
1467        trace!("END record");
1468        // Finished reading file.
1469
1470        if !self.table_offsets_at_start {
1471            // table-offsets is stored in END record.
1472            read_offset_table(reader)?;
1473        }
1474
1475        // The padding string makes sure that the byte length of the END record inclusive record-ID is exactly 256.
1476        let _padding_string = read_byte_string(reader)?;
1477
1478        // Type of integrity check: None, CRC32 or CHECKSUM32.
1479        let validation_scheme = read_unsigned_integer(reader)?;
1480
1481        match validation_scheme {
1482            0 => {
1483                // No validation.
1484                trace!("No integrity validation.");
1485            }
1486            1 => {
1487                // CRC32, checksum length = 4
1488                let crc32_expected = reader.read_u32::<LittleEndian>()?;
1489                trace!("CRC32 (from file): {:x}", crc32_expected);
1490                // TODO: Validate checksum
1491            }
1492            2 => {
1493                // CHECKSUM32, checksum length = 4
1494                // CHECKSUM32 is the simple arithmetic addition of all bytes from the first
1495                // byte of the START record until the `validation_scheme` byte of this END record.
1496                let checksum32_expected = reader.read_u32::<LittleEndian>()?;
1497                trace!("CHECKSUM32 (from file): {:x}", checksum32_expected);
1498                // TODO: Validate checksum
1499            }
1500            v => {
1501                return Err(OASISReadError::UnknownValidationScheme(v)); // Invalid validation scheme.
1502            }
1503        }
1504
1505        Ok(())
1506    }
1507
1508    // fn read_xyz<R: Read>(&mut self, reader: &mut R, layout: &mut L) -> Result<(), OASISReadError> {
1509    //     Ok(())
1510    // }
1511
1512    fn read_cell_name<R: Read>(
1513        &mut self,
1514        reader: &mut R,
1515        layout: &mut L,
1516        record_id: u32,
1517    ) -> Result<(), OASISReadError> {
1518        // CELLNAME record
1519        trace!("CELLNAME record");
1520
1521        let cell_name = read_name_string(reader)?;
1522        trace!("cell name = {}", &cell_name);
1523
1524        let id = if record_id == 3 {
1525            // Implicit IDs.
1526            if self.id_counters.cellname.id_mode == IdMode::Expl {
1527                return Err(OASISReadError::MixedImplExplCellnameModes); // Implicit and explicit CELLNAME modes cannot be mixed.
1528            };
1529            self.id_counters.cellname.id_mode = IdMode::Impl; // Remember mode.
1530            self.id_counters.cellname.next() // Infinite sequence, unwrap does not fail.
1531        } else {
1532            // Explicit IDs.
1533            if self.id_counters.cellname.id_mode == IdMode::Impl {
1534                return Err(OASISReadError::MixedImplExplCellnameModes); // Implicit and explicit CELLNAME modes cannot be mixed.
1535            };
1536            self.id_counters.cellname.id_mode = IdMode::Expl; // Remember mode.
1537            read_unsigned_integer(reader)?
1538        };
1539
1540        // Store cell name.
1541        // Return an error if the cell name already exists.
1542        if self.m_cell_names.insert(id, cell_name.clone()).is_some() {
1543            return Err(OASISReadError::CellnameIdAlreadyPresent(id));
1544        }
1545        self.modal.reset();
1546
1547        // Resolve forward references.
1548        if let Some(idx) = self.m_cell_names_forward_references.remove(&id) {
1549            // TODO: Handle case when name is already used.
1550            if let Some(_existing_cell) = layout.cell_by_name(&cell_name) {
1551                warn!("Cell already exists: {}", cell_name);
1552                // Find a cell name that does not exit by appending a counter.
1553                // let new_cell_name = (1..).into_iter()
1554                //     .map(|i| format!("{}$${}", cell_name, i))
1555                //     .find(|name| layout.cell_by_name(name).is_none())
1556                //     .unwrap();
1557            }
1558            layout.rename_cell(&idx, cell_name.clone().into());
1559        }
1560
1561        // Subsequent PROPERTY records may be associated with the cell with this name.
1562        self.property_parent = PropertyParent::CellName(cell_name);
1563
1564        Ok(())
1565    }
1566
1567    fn read_property_record<R: Read>(
1568        &mut self,
1569        reader: &mut R,
1570        layout: &mut L,
1571        record_id: u32,
1572    ) -> Result<(), OASISReadError> {
1573        // PROPERTY record.
1574        // PROPERTY records follow the records they are associated with.
1575        // Updates `last_property_name` and `last_value_list` modal variables.
1576
1577        // 29 specifies a duplicate of the most recently seen property.
1578
1579        trace!("PROPERTY record");
1580
1581        let (property_name_or_ref, property_values) = if record_id == 28 {
1582            let prop_info_byte = read_byte(reader)?;
1583            let b = |index| (prop_info_byte >> index) & 1u8 == 1u8;
1584            let is_name_reference_explicit = b(2); // C
1585            let use_last_value_list = b(3); // V
1586            let _is_standard_property = b(0); // S, TODO: How to handle this?
1587            let uuuu = ((prop_info_byte >> 4) & 0xF).into(); // Upper nibble.
1588
1589            let property_name_or_ref = if is_name_reference_explicit {
1590                let is_ref_number_present = b(1);
1591                if is_ref_number_present {
1592                    // Property name is defined by the reference number.
1593                    // This can be a forward reference.
1594                    let ref_number = read_unsigned_integer(reader)?; // Reference number to property name.
1595                    let property_name = self.m_propnames.get(&ref_number);
1596                    trace!("ref_number = {}", ref_number);
1597                    // property_name.cloned().ok_or(OASISReadError::PropStringIdNotFound(ref_number))?
1598                    match property_name {
1599                        Some(name) => NameOrRef::Name(name.clone()),
1600                        None => NameOrRef::NameRef(ref_number), // This is a forward reference.
1601                    }
1602                } else {
1603                    NameOrRef::Name(read_name_string(reader)?)
1604                }
1605            } else {
1606                // Implicit name: Modal variable `last_property_name` is used.
1607                self.modal
1608                    .last_property_name
1609                    .take()
1610                    .ok_or(OASISReadError::ModalLastPropertyNameNotDefined)?
1611            };
1612
1613            let values = if !use_last_value_list {
1614                let num_values = if uuuu == 15 {
1615                    read_unsigned_integer(reader)?
1616                } else {
1617                    uuuu
1618                };
1619
1620                // Read property values.
1621                let mut prop_value_list = Vec::with_capacity(num_values.min(1 << 20) as usize);
1622                for _i in 0..num_values {
1623                    let prop = read_property_value(reader)?;
1624                    prop_value_list.push(prop)
1625                }
1626                prop_value_list
1627            } else {
1628                // uuuu must be 0
1629                if uuuu != 0 {
1630                    log::error!("The bits 'uuuu' must be 0 but is {}", uuuu);
1631                    return Err(OASISReadError::FormatError); // TODO More specific error type: "uuuu must be 0".
1632                }
1633
1634                self.modal
1635                    .last_value_list
1636                    .take()
1637                    .ok_or(OASISReadError::ModalLastValueListNotDefined)?
1638            };
1639
1640            // Update modal variables.
1641            self.modal.last_property_name = Some(property_name_or_ref.clone());
1642            self.modal.last_value_list = Some(values.clone());
1643
1644            (property_name_or_ref, values)
1645        } else {
1646            // Use the last property.
1647            (
1648                self.modal
1649                    .last_property_name
1650                    .clone()
1651                    .ok_or(OASISReadError::ModalLastPropertyNameNotDefined)?,
1652                self.modal
1653                    .last_value_list
1654                    .clone()
1655                    .ok_or(OASISReadError::ModalLastValueListNotDefined)?,
1656            )
1657        };
1658
1659        trace!("property name or reference = {:?}", &property_name_or_ref);
1660        trace!("property values = {:?}", &property_values);
1661
1662        match property_name_or_ref {
1663            NameOrRef::Name(property_name) => {
1664                // Name is known.
1665                trace!("property name = {}", &property_name);
1666
1667                // Store the properties!
1668                Self::set_property(
1669                    layout,
1670                    &self.property_parent,
1671                    &property_name,
1672                    &property_values,
1673                    &self.m_propstrings,
1674                );
1675            }
1676            NameOrRef::NameRef(property_name_ref) => {
1677                // Forward reference to a property name.
1678                trace!(
1679                    "Property name is a forward reference = {}",
1680                    &property_name_ref
1681                );
1682
1683                // Remember forward reference to be resolved later.
1684                self.m_property_name_forward_references
1685                    .entry(property_name_ref)
1686                    .or_default()
1687                    .push((self.property_parent.clone(), property_values))
1688            }
1689        }
1690
1691        Ok(())
1692    }
1693}
1694
1695/// Read an OASIS layout.
1696pub fn read_layout<R: Read, L: LayoutEdit<Coord = SInt>>(
1697    reader: &mut R,
1698    layout: &mut L,
1699) -> Result<(), OASISReadError> {
1700    let reader_state: ReaderState<L> = Default::default();
1701    reader_state.read_layout(reader, layout)
1702}