reda-lib 0.2.0

Liberty file library
Documentation
mod ast;
mod library;
mod cell;
mod pin;
pub use ast::*;
pub use library::*;
pub use cell::*;
pub use pin::*;

use std::collections::HashMap;
use crate::error::LibError;

pub trait Model {
    fn attrs(&self) -> &HashMap<String, LibValue>;
    fn groups(&self) -> &[LibGroup];
    fn attr(&self, name: &str) -> Option<&LibValue> {
        self.attrs().get(name)
    }
    fn kind_groups(&self, kind: &str) -> impl IntoIterator<Item = &LibGroup> {
        self.groups().into_iter().filter(move |g| g.kind == kind)
    }
}

#[derive(Debug, PartialEq, Clone, Default)]
pub struct LibGroup {
    pub kind: String,
    pub params: Vec<String>,

    pub attrs: HashMap<String, LibValue>,
    pub groups: Vec<LibGroup>,
}

impl LibGroup {
    pub fn new<S: Into<String>, P: Into<Vec<String>>>(kind: S, params: P) -> Self {
        Self {
            kind: kind.into(),
            params: params.into(),
            ..Default::default()
        }
    }
}

impl Model for LibGroup {
    fn attrs(&self) -> &HashMap<String, LibValue> {
        &self.attrs
    }

    fn groups(&self) -> &[LibGroup] {
        &self.groups
    }
}

impl LibGroup {
    pub fn expect_name(&mut self) -> Result<String, LibError> {
        if self.params.len() != 1 {
            Err(LibError::LibraryParamLenUnmatch)?
        }
        Ok(self.params[0].clone())
    }

    pub fn expect_ident_attr(&mut self, attr_name: &str) -> Result<String, LibError> {
        if let Some(value) = self.attrs.remove(attr_name) {
            let s = value.into_ident()?;
            Ok(s)
        } else {
            Err(LibError::MissAttr(attr_name.to_string()))
        }
    }

    pub fn expect_ident_attr_opt(&mut self, attr_name: &str) -> Result<Option<String>, LibError> {
        if let Some(value) = self.attrs.remove(attr_name) {
            let s = value.into_ident()?;
            Ok(Some(s))
        } else {
            Ok(None)
        }
    }

    pub fn expect_string_attr_opt(&mut self, attr_name: &str) -> Result<Option<String>, LibError> {
        if let Some(value) = self.attrs.remove(attr_name) {
            let s = value.into_string()?;
            Ok(Some(s))
        } else {
            Ok(None)
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_cells() {
        let lib = LibLibrary::load_file("./data/cells.lib").unwrap();
        let and2 = lib.cell("AND2").unwrap();
        let pin = and2.pin("o").unwrap();
        println!("{:#?}", pin.function);
    }
}