1use uniquify::Names;
4
5use super::*;
6
7pub struct MergedMapping {
9 cells: HashMap<CellId, CellId>,
10 primitives: HashMap<PrimitiveId, PrimitiveId>,
11}
12
13struct Merger<'a, S: Schema + ?Sized> {
14 cell_mapping: HashMap<CellId, CellId>,
16 primitive_mapping: HashMap<PrimitiveId, PrimitiveId>,
18 names: Names<CellId>,
20 dst: &'a mut LibraryBuilder<S>,
21 src: LibraryBuilder<S>,
22 merge_cells: Option<Vec<CellId>>,
26}
27
28impl<'a, S: Schema + ?Sized> Merger<'a, S> {
29 #[inline]
30 fn new(dst: &'a mut LibraryBuilder<S>, src: LibraryBuilder<S>) -> Self {
31 Self {
32 cell_mapping: HashMap::with_capacity(src.cells.len()),
33 primitive_mapping: HashMap::with_capacity(src.primitives.len()),
34 names: Names::with_capacity(src.cells.len() + dst.cells.len()),
35 dst,
36 src,
37 merge_cells: None,
38 }
39 }
40
41 #[inline]
42 fn merge_cells(
43 dst: &'a mut LibraryBuilder<S>,
44 src: LibraryBuilder<S>,
45 cells: impl IntoIterator<Item = CellId>,
46 ) -> Self {
47 Self {
48 cell_mapping: HashMap::with_capacity(src.cells.len()),
49 primitive_mapping: HashMap::with_capacity(src.primitives.len()),
50 names: Names::with_capacity(src.cells.len() + dst.cells.len()),
51 dst,
52 src,
53 merge_cells: Some(cells.into_iter().collect()),
54 }
55 }
56
57 fn merge(mut self) -> MergedMapping {
58 for (id, cell) in self.dst.cells() {
59 self.names.reserve_name(id, cell.name());
60 }
61 let mut cells: Vec<_> = if let Some(cells) = self.merge_cells.as_ref() {
62 self.src
63 .cells_used_by(cells.iter().copied())
64 .iter()
65 .map(|&id| (id, self.src.cell(id).clone()))
66 .collect()
67 } else {
68 self.src.cells.drain(..).collect()
69 };
70 let primitives: Vec<_> = self.src.primitives.drain(..).collect();
71 for (id, cell) in cells.iter_mut() {
72 self.assign_cell_identifiers(*id, cell);
73 }
74 for (id, _) in primitives.iter() {
75 self.assign_primitive_identifiers(*id);
76 }
77 for (id, cell) in cells {
78 self.merge_cell(id, cell);
79 }
80 for (id, primitive) in primitives {
81 self.merge_primitive(id, primitive);
82 }
83
84 MergedMapping {
85 cells: self.cell_mapping,
86 primitives: self.primitive_mapping,
87 }
88 }
89
90 fn assign_cell_identifiers(&mut self, id: CellId, cell: &mut Cell) {
91 let n_id = self.dst.alloc_cell_id();
92 let n_name = self.names.assign_name(n_id, &cell.name);
93 self.cell_mapping.insert(id, n_id);
94 cell.name = n_name;
95 }
96
97 fn assign_primitive_identifiers(&mut self, id: PrimitiveId) {
98 let n_id = self.dst.alloc_primitive_id();
99 self.primitive_mapping.insert(id, n_id);
100 }
101
102 fn merge_cell(&mut self, id: CellId, mut cell: Cell) {
103 for (_, inst) in cell.instances.iter_mut() {
104 match inst.child() {
105 ChildId::Cell(c) => {
106 inst.child = (*self.cell_mapping.get(&c).unwrap()).into();
107 }
108 ChildId::Primitive(p) => {
109 inst.child = (*self.primitive_mapping.get(&p).unwrap()).into();
110 }
111 }
112 }
113 let n_id = self.cell_mapping.get(&id).unwrap();
114 self.dst.add_cell_with_id(*n_id, cell);
115 }
116
117 fn merge_primitive(&mut self, id: PrimitiveId, primitive: S::Primitive) {
118 let n_id = self.primitive_mapping.get(&id).unwrap();
119 self.dst.add_primitive_with_id(*n_id, primitive);
120 }
121}
122
123impl MergedMapping {
124 pub fn new_cell_id(&self, old_cell_id: CellId) -> CellId {
132 self.cells.get(&old_cell_id).copied().unwrap()
133 }
134 pub fn new_primitive_id(&self, old_primitive_id: PrimitiveId) -> PrimitiveId {
142 self.primitives.get(&old_primitive_id).copied().unwrap()
143 }
144}
145
146impl<S: Schema + ?Sized> LibraryBuilder<S> {
147 pub fn merge(&mut self, other: Self) -> MergedMapping {
149 Merger::new(self, other).merge()
150 }
151
152 pub fn merge_cells(
154 &mut self,
155 other: Self,
156 cells: impl IntoIterator<Item = CellId>,
157 ) -> MergedMapping {
158 Merger::merge_cells(self, other, cells).merge()
159 }
160}