liberty-db 0.4.6

`liberty` data structre
//! <script>
//! IFRAME('https://zao111222333.github.io/liberty-db/2020.09/reference_manual.html');
//! </script>

mod items;
pub use items::*;

use crate::{
  ast::{AttributeList, GroupComments},
  cell::Cell,
  units, GroupSet,
};
use std::collections::HashMap;
use std::fmt::{Display, Write};

#[derive(Debug, Clone, derivative::Derivative)]
#[derivative(Default)]
#[derive(liberty_macros::Group)]
#[mut_set_derive::item(
  macro(derive(Debug, Clone);
        derive(derivative::Derivative);
        derivative(Default);),
  attr_filter(derivative;)
)]
pub struct Library {
  #[id]
  #[liberty(name)]
  pub name: String,
  #[liberty(comments)]
  _comments: GroupComments<Self>,
  #[liberty(undefined)]
  _undefined: AttributeList,
  /// Valid values are 1ps, 10ps, 100ps, and 1ns. The default is 1ns.
  /// <a name ="reference_link" href="
  /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=42.25&end=42.30
  /// ">Reference</a>
  #[liberty(simple)]
  pub time_unit: units::TimeUnit,
  /// This attribute specifies the unit for all capacitance
  /// values within the logic library, including
  /// default capacitances, max_fanout capacitances,
  /// pin capacitances, and wire capacitances.
  /// <a name ="reference_link" href="
  /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=44.7&end=44.19
  /// ">Reference</a>
  #[liberty(complex(type = Option))]
  pub capacitive_load_unit: Option<units::CapacitiveLoadUnit>,
  /// Valid values are 1mV, 10mV, 100mV, and 1V. The default is 1V.
  /// <a name ="reference_link" href="
  /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=43.2&end=43.9
  /// ">Reference</a>
  #[liberty(simple)]
  pub voltage_unit: units::VoltageUnit,
  /// The valid values are 1uA, 10uA, 100uA, 1mA, 10mA, 100mA, and 1A.
  /// **No default exists for the `current_unit` attribute if the attribute is omitted.**
  /// <a name ="reference_link" href="
  /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=43.12&end=43.24
  /// ">Reference</a>
  #[liberty(simple(type = Option))]
  pub current_unit: Option<units::CurrentUnit>,
  /// Valid unit values are 1ohm, 10ohm, 100ohm, and 1kohm.
  /// **No default exists for `pulling_resistance_unit` if the attribute is omitted.**
  /// <a name ="reference_link" href="
  /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=43.25&end=44.4
  /// ">Reference</a>
  #[liberty(simple(type = Option))]
  pub pulling_resistance_unit: Option<units::PullingResistanceUnit>,
  /// This attribute indicates the units of the power values
  /// in the library. If this attribute is missing, the
  /// leakage-power values are expressed without units.
  /// Valid values are 1W, 100mW, 10mW, 1mW, 100nW, 10nW, 1nW, 100pW, 10pW, and 1pW.
  /// <a name ="reference_link" href="
  /// https://zao111222333.github.io/liberty-db/2020.09/user_guide.html?field=null&bgn=44.22&end=44.31
  /// ">Reference</a>
  #[liberty(simple(type = Option))]
  pub leakage_power_unit: Option<units::LeakagePowerUnit>,
  #[liberty(simple)]
  #[derivative(Default(value = "80.0"))]
  pub slew_upper_threshold_pct_rise: f64,
  #[liberty(group(type = Set))]
  pub cell: GroupSet<Cell>,
  pub voltage_map: HashMap<String, f64>,
  pub sensitization_map: HashMap<String, Sensitization>,
}

impl Display for Library {
  /// ```
  /// use liberty_db::library::Library;
  /// use std::{
  /// fs::{self, File},
  /// io::{BufWriter, Write},
  /// path::Path};
  /// let library  = Library::default();
  /// let mut writer = BufWriter::new(File::create(Path::new("out.lib"))?);
  /// write!(&mut writer, "{}", library)?;
  /// ```
  /// Format [Library] struct as `.lib` file
  #[inline]
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
    let ff = &mut crate::ast::CodeFormatter::new(f, "  ");
    <AttriComment as Format>::liberty(self.comment(), "", ff)?;
    self.fmt_liberty("library", ff)
  }
}
use crate::ast::parser;
use crate::ast::{AttriComment, Format, GroupAttri, ParserError};
impl Library {
  // /// Format [Library] struct as `.lib` file
  // #[inline]
  // pub fn fmt<T: Write>(&self, w: &mut T) -> std::fmt::Result {
  //   let f = &mut crate::ast::CodeFormatter::new(w, "  ");
  //   <AttriComment as Format>::liberty(self.comment(), "", f)?;
  //   self.fmt_liberty("library", f)
  // }
  /// Parse `.lib` file as a [Library] struct.
  #[inline]
  pub fn parse<'a>(i: &'a str) -> Result<Self, ParserError<'a>> {
    let mut line_num = 1;
    let input = match parser::comment_space_newline(i) {
      Ok((input, n)) => {
        line_num += n;
        input
      }
      Err(e) => return Err(ParserError::NomError(line_num, e)),
    };
    let (input, key) = match parser::key::<nom::error::Error<&str>>(input) {
      Ok(res) => res,
      Err(e) => return Err(ParserError::NomError(line_num, e)),
    };
    if key == "library" {
      match <Self as GroupAttri>::nom_parse(input, &mut line_num) {
        Err(e) => return Err(ParserError::NomError(line_num, e)),
        Ok((_, Err(e))) => return Err(ParserError::IdError(line_num, e)),
        Ok((_, Ok(l))) => return Ok(l),
      }
    } else {
      Err(ParserError::Other(line_num, format!("Need key=library, find={}", key)))
    }
  }
}