use crate::iron_shapes::prelude::*;
use super::prelude::*;
use super::shape_collection::{Shapes, Shape};
use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use genawaiter::rc::Gen;
use std::hash::{Hash, Hasher};
use crate::property_storage::{PropertyStore, WithProperties};
pub type CellReference<C> = Rc<RefCell<Cell<C>>>;
#[derive(Clone, Debug)]
pub struct Cell<C: CoordinateType> {
name: RefCell<Option<String>>,
pub(super) self_reference: RefCell<Weak<Self>>,
index: CellIndex,
cell_instances: RefCell<HashMap<CellInstId, Rc<CellInstance<C>>>>,
cell_instance_index_generator: RefCell<CellInstIndexGenerator>,
shapes_map: RefCell<HashMap<LayerIndex, Rc<Shapes<C>>>>,
cell_references: RefCell<HashSet<Rc<CellInstance<C>>>>,
dependencies: RefCell<HashMap<CellIndex, (Weak<Self>, usize)>>,
dependent_cells: RefCell<HashMap<CellIndex, (Weak<Self>, usize)>>,
cell_properties: RefCell<PropertyStore<String>>,
pub (super) instance_properties: RefCell<HashMap<CellInstId, PropertyStore<String>>>,
}
impl<C: CoordinateType> Eq for Cell<C> {}
impl<C: CoordinateType> PartialEq for Cell<C> {
fn eq(&self, other: &Self) -> bool {
self.index == other.index
}
}
impl<C: CoordinateType> Hash for Cell<C> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.index.hash(state);
}
}
impl<C: CoordinateType> Cell<C> {
pub(super) fn new(name: Option<String>, index: CellIndex) -> Self {
Cell {
name: RefCell::new(name),
self_reference: RefCell::default(),
cell_instances: Default::default(),
index: index,
shapes_map: Default::default(),
cell_instance_index_generator: Default::default(),
cell_references: Default::default(),
dependencies: Default::default(),
dependent_cells: Default::default(),
cell_properties: Default::default(),
instance_properties: Default::default(),
}
}
pub fn index(&self) -> CellIndex {
self.index
}
pub fn name(&self) -> Option<String> {
self.name.borrow().clone()
}
pub(crate) fn set_name(&self, name: Option<String>) -> Option<String> {
self.name.replace(name)
}
pub fn clear_shapes(&self) -> () {
self.shapes_map.borrow_mut().clear();
}
pub fn clear_instances(&self) -> () {
let all_instances: Vec<_> = self.cell_instances.borrow().values().cloned().collect();
for inst in all_instances {
self.remove_cell_instance(&inst)
}
}
pub fn clear(&self) -> () {
self.clear_shapes();
self.clear_instances();
}
pub fn clear_layer(&self, layer_index: LayerIndex) -> () {
self.shapes_map.borrow_mut().remove(&layer_index);
}
pub fn create_instance(&self, template_cell: &Rc<Cell<C>>, transform: SimpleTransform<C>) -> Rc<CellInstance<C>> {
{
let mut stack: Vec<Rc<Cell<C>>> = vec![self.self_reference().upgrade().unwrap()];
while let Some(c) = stack.pop() {
if c.eq(&template_cell) {
panic!("Cannot create recursive instances.");
}
c.dependent_cells.borrow().values()
.map(|(dep, _)| dep.upgrade().unwrap()) .for_each(|dep| stack.push(dep));
}
}
let index = self.cell_instance_index_generator.borrow_mut().next();
let cell_inst = CellInstance {
id: index,
parent_cell_id: self.index(),
cell: Rc::downgrade(template_cell),
parent_cell: self.self_reference.borrow().clone(),
transform,
};
let rc_cell_inst = Rc::new(cell_inst);
self.cell_instances.borrow_mut().insert(index, rc_cell_inst.clone());
{
let mut dependencies = self.dependencies.borrow_mut();
dependencies.entry(template_cell.index())
.and_modify(|(_, c)| *c += 1)
.or_insert((Rc::downgrade(template_cell), 1)); }
{
let mut dependent = template_cell.dependent_cells.borrow_mut();
dependent.entry(self.index())
.and_modify(|(_, c)| *c += 1)
.or_insert((self.self_reference(), 1)); }
let was_not_present = template_cell.cell_references.borrow_mut()
.insert(rc_cell_inst.clone());
debug_assert!(was_not_present, "Cell instance with this index already existed!");
#[cfg(debug_assertions)] {
debug_assert_eq!(self.num_references(), self.dependent_cells.borrow().values()
.map(|(_, n)| n).sum(), "self.num_references() is not consistent with the number of dependent cell.");
debug_assert_eq!(template_cell.num_references(), template_cell.dependent_cells.borrow().values()
.map(|(_, n)| n).sum(), "cell.num_references() is not consistent with the number of dependent cells.");
let dependencies = self.dependencies.borrow()
.values()
.map(|(c, _)| c.upgrade().unwrap().index())
.sorted().collect_vec();
let dependencies_derived = self.each_inst()
.map(|c| c.cell_id())
.unique()
.sorted()
.collect_vec();
debug_assert_eq!(dependencies, dependencies_derived);
}
rc_cell_inst
}
pub fn num_references(&self) -> usize {
self.cell_references.borrow().len()
}
pub fn remove_cell_instance(&self, cell_instance: &Rc<CellInstance<C>>) -> () {
assert!(cell_instance.parent_cell().ptr_eq(&self.self_reference()),
"Cell instance does not live in this cell.");
{
let mut dependencies = self.dependencies.borrow_mut();
let template_cell_id = cell_instance.cell_id();
let (_, count) = dependencies.entry(template_cell_id)
.or_insert((Weak::new(), 0));
*count -= 1;
if *count == 0 {
dependencies.remove(&template_cell_id);
}
}
{
let template_cell = cell_instance.cell().upgrade().unwrap();
let mut dependent = template_cell.dependent_cells.borrow_mut();
let (_, count) = dependent.entry(self.index())
.or_insert((Weak::new(), 0));
*count -= 1;
if *count == 0 {
dependent.remove(&self.index());
}
}
self.cell_instances.borrow_mut().remove(&cell_instance.id())
.unwrap();
let remove_successful = cell_instance.cell().upgrade().unwrap()
.cell_references.borrow_mut()
.remove(cell_instance);
assert!(remove_successful, "Failed to remove cell instance from 'cell_references'.");
#[cfg(debug_assertions)]
{
debug_assert_eq!(self.num_references(), self.dependent_cells.borrow().values()
.map(|(_, n)| n).sum());
let instance_ref = cell_instance.cell().upgrade().unwrap();
debug_assert_eq!(instance_ref.num_references(), instance_ref.dependent_cells.borrow().values()
.map(|(_, n)| n).sum());
}
}
pub fn self_reference(&self) -> Weak<Self> {
self.self_reference.borrow().clone()
}
pub fn shapes(&self, layer_index: LayerIndex) -> Option<Rc<Shapes<C>>> {
self.shapes_map.borrow().get(&layer_index).cloned()
}
pub fn shapes_get_or_create(&self, layer_index: LayerIndex) -> Rc<Shapes<C>> {
if let Some(shapes) = self.shapes(layer_index) {
shapes
} else {
let shapes = Shapes::new_rc_with_parent(self.self_reference.borrow().clone());
self.shapes_map.borrow_mut().insert(layer_index, shapes.clone());
shapes
}
}
pub fn each_used_layer(&self) -> Vec<LayerIndex> {
self.shapes_map.borrow().iter()
.filter(|(_idx, s)| s.len() > 0)
.map(|(&i, _)| i)
.collect()
}
pub fn each_shape(&self, layer_index: LayerIndex) -> impl Iterator<Item=Rc<Shape<C>>> + '_ {
let generator = Gen::new(|co| async move {
if let Some(shapes) = self.shapes(layer_index) {
for s in shapes.each_shape() {
co.yield_(s).await;
}
};
});
generator.into_iter()
}
pub fn each_inst(&self) -> impl Iterator<Item=Rc<CellInstance<C>>> + '_ {
let generator = Gen::new(|co| async move {
for i in self.cell_instances.borrow().values().cloned() {
co.yield_(i).await;
}
});
generator.into_iter()
}
pub fn is_leaf(&self) -> bool {
self.cell_instances.borrow().is_empty()
}
}
impl<C: CoordinateType> TryBoundingBox<C> for Cell<C> {
fn try_bounding_box(&self) -> Option<Rect<C>> {
let shapes_bbox = self.shapes_map.borrow().values()
.filter_map(|shapes| shapes.try_bounding_box())
.fold1(|a, b| a.add_rect(&b));
shapes_bbox
}
}
impl<C: CoordinateType> WithProperties for Cell<C> {
type Key = String;
fn with_properties<F, R>(&self, f: F) -> R
where F: FnOnce(Option<&PropertyStore<Self::Key>>) -> R {
f(Some(&self.cell_properties.borrow()))
}
fn with_properties_mut<F, R>(&self, f: F) -> R
where F: FnOnce(&mut PropertyStore<Self::Key>) -> R {
f(&mut self.cell_properties.borrow_mut())
}
}