use std::{
fmt,
ops::{Deref, DerefMut},
vec,
};
use indexmap::IndexMap;
use crate::ast::{GroupItem, LibertyAst, Value};
#[derive(Debug, PartialEq, Clone)]
pub struct Liberty(pub Vec<Group>);
impl Liberty {
pub fn to_ast(self) -> LibertyAst {
LibertyAst(self.0.into_iter().map(|g| g.into_group_item()).collect())
}
pub fn from_ast(ast: LibertyAst) -> Self {
Liberty(ast.0.into_iter().map(Group::from_group_item).collect())
}
}
impl Deref for Liberty {
type Target = [Group];
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl DerefMut for Liberty {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.deref_mut()
}
}
impl From<LibertyAst> for Liberty {
fn from(ast: LibertyAst) -> Self {
Liberty::from_ast(ast)
}
}
impl fmt::Display for Liberty {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.clone().to_ast().fmt(f)
}
}
impl IntoIterator for Liberty {
type Item = Group;
type IntoIter = ::std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Attribute {
Simple(Value),
Complex(Vec<Value>),
}
#[derive(Debug, PartialEq, Clone)]
pub struct Group {
pub type_: String,
pub name: String,
pub attributes: IndexMap<String, Vec<Attribute>>,
pub subgroups: Vec<Group>,
}
impl Group {
pub fn new(type_: &str, name: &str) -> Self {
Self {
type_: type_.to_string(),
name: name.to_string(),
attributes: IndexMap::new(),
subgroups: vec![],
}
}
pub fn from_group_item(group_item: GroupItem) -> Self {
let (type_, name, items) = group_item.group();
let mut attributes: IndexMap<String, Vec<Attribute>> = IndexMap::new();
let mut subgroups = vec![];
for item in items {
match item {
GroupItem::SimpleAttr(name, value) => {
if attributes.contains_key(&name) {
attributes
.get_mut(&name)
.unwrap()
.push(Attribute::Simple(value));
} else {
attributes.insert(name, vec![Attribute::Simple(value)]);
}
}
GroupItem::ComplexAttr(name, value) => {
if attributes.contains_key(&name) {
attributes
.get_mut(&name)
.unwrap()
.push(Attribute::Complex(value));
} else {
attributes.insert(name, vec![Attribute::Complex(value)]);
}
}
GroupItem::Group(type_, name, items) => {
subgroups.push(Group::from_group_item(GroupItem::Group(type_, name, items)));
}
_ => {}
}
}
Self {
name,
type_,
attributes,
subgroups,
}
}
pub fn into_group_item(self) -> GroupItem {
let mut items: Vec<GroupItem> =
Vec::with_capacity(self.attributes.len() + self.subgroups.len());
items.extend(self.attributes.into_iter().flat_map(|(name, attrs)| {
attrs.into_iter().map(move |attr| match attr {
Attribute::Simple(value) => GroupItem::SimpleAttr(name.clone(), value),
Attribute::Complex(value) => GroupItem::ComplexAttr(name.clone(), value),
})
}));
items.extend(self.subgroups.into_iter().map(|g| g.into_group_item()));
GroupItem::Group(self.type_, self.name, items)
}
pub fn complex_attribute(&self, name: &str) -> Option<&Vec<Value>> {
self.attributes.get(name).and_then(|attrs| {
attrs.first().and_then(|attr| match attr {
Attribute::Complex(value) => Some(value),
_ => None,
})
})
}
pub fn simple_attribute(&self, name: &str) -> Option<&Value> {
self.attributes.get(name).and_then(|attrs| {
attrs.first().and_then(|attr| match attr {
Attribute::Simple(value) => Some(value),
_ => None,
})
})
}
pub fn iter_complex_attributes(&self) -> impl Iterator<Item = (&String, &Vec<Value>)> {
self.attributes.iter().flat_map(|(name, attrs)| {
attrs.iter().filter_map(move |attr| match attr {
Attribute::Complex(value) => Some((name, value)),
_ => None,
})
})
}
pub fn iter_complex_attributes_mut(
&mut self,
) -> impl Iterator<Item = (&String, &mut Vec<Value>)> {
self.attributes.iter_mut().flat_map(|(name, attrs)| {
attrs.iter_mut().filter_map(move |attr| match attr {
Attribute::Complex(value) => Some((name, value)),
_ => None,
})
})
}
pub fn iter_simple_attributes(&self) -> impl Iterator<Item = (&String, &Value)> {
self.attributes.iter().flat_map(|(name, attrs)| {
attrs.iter().filter_map(move |attr| match attr {
Attribute::Simple(value) => Some((name, value)),
_ => None,
})
})
}
pub fn iter_simple_attributes_mut(&mut self) -> impl Iterator<Item = (&String, &mut Value)> {
self.attributes.iter_mut().flat_map(|(name, attrs)| {
attrs.iter_mut().filter_map(move |attr| match attr {
Attribute::Simple(value) => Some((name, value)),
_ => None,
})
})
}
pub fn iter_subgroups_of_type<'a>(&'a self, type_: &'a str) -> impl Iterator<Item = &'a Group> {
self.subgroups.iter().filter(move |g| g.type_ == type_)
}
pub fn iter_subgroups_of_type_mut<'a>(
&'a mut self,
type_: &'a str,
) -> impl Iterator<Item = &'a mut Group> {
self.subgroups.iter_mut().filter(move |g| g.type_ == type_)
}
pub fn iter_subgroups(&self) -> impl Iterator<Item = &Group> {
self.subgroups.iter()
}
pub fn iter_subgroups_mut(&mut self) -> impl Iterator<Item = &mut Group> {
self.subgroups.iter_mut()
}
pub fn get_cell(&self, name: &str) -> Option<&Group> {
self.iter_subgroups_of_type("cell").find(|g| g.name == name)
}
pub fn get_cell_mut(&mut self, name: &str) -> Option<&mut Group> {
self.iter_subgroups_of_type_mut("cell")
.find(|g| g.name == name)
}
pub fn get_pin(&self, name: &str) -> Option<&Group> {
self.iter_subgroups_of_type("pin").find(|g| g.name == name)
}
pub fn get_pin_mut(&mut self, name: &str) -> Option<&mut Group> {
self.iter_subgroups_of_type_mut("pin")
.find(|g| g.name == name)
}
pub fn iter_cells(&self) -> impl Iterator<Item = &Group> {
self.iter_subgroups_of_type("cell")
}
pub fn iter_cells_mut(&mut self) -> impl Iterator<Item = &mut Group> {
self.iter_subgroups_of_type_mut("cell")
}
pub fn iter_pins(&self) -> impl Iterator<Item = &Group> {
self.iter_subgroups_of_type("pin")
}
pub fn iter_pins_mut(&mut self) -> impl Iterator<Item = &mut Group> {
self.iter_subgroups_of_type_mut("pin")
}
}