libreda_db/rw_reference_access/
hierarchy_reference_access.rs1#![allow(missing_docs)]
7
8use crate::traits::{HierarchyBase, HierarchyEdit};
9use std::hash::{Hash, Hasher};
10use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
11
12pub struct RwRefAccess<T> {
19 base: Arc<RwLock<T>>,
20}
21
22impl<T> RwRefAccess<T> {
23 pub fn new(base: T) -> Self {
24 Self {
25 base: Arc::new(RwLock::new(base)),
26 }
27 }
28
29 pub fn read(&self) -> RwLockReadGuard<'_, T> {
33 self.base.read().expect("Failed to get read access.")
34 }
35
36 pub fn write(&self) -> RwLockWriteGuard<'_, T> {
43 self.base.write().expect("Failed to get write access.")
44 }
45}
46
47impl<T> Clone for RwRefAccess<T> {
48 fn clone(&self) -> Self {
49 Self {
50 base: self.base.clone(),
51 }
52 }
53}
54
55impl<T> Eq for RwRefAccess<T> {}
56
57impl<T> PartialEq for RwRefAccess<T> {
58 fn eq(&self, other: &Self) -> bool {
59 Arc::ptr_eq(&self.base, &other.base)
60 }
61}
62
63impl<T> Hash for RwRefAccess<T> {
64 fn hash<H: Hasher>(&self, state: &mut H) {
65 Arc::as_ptr(&self.base).hash(state)
66 }
67}
68
69impl<H: HierarchyBase> RwRefAccess<H> {
70 fn cell(&self, id: H::CellId) -> CellRef<H> {
72 CellRef {
73 base: self.clone(),
74 id,
75 }
76 }
77
78 fn cell_inst(&self, id: H::CellInstId) -> CellInstRef<H> {
80 CellInstRef {
81 base: self.clone(),
82 id,
83 }
84 }
85
86 pub fn each_cell(&self) -> Vec<CellRef<H>> {
88 self.read().each_cell().map(|id| self.cell(id)).collect()
89 }
90
91 pub fn num_cells(&self) -> usize {
93 self.read().num_cells()
94 }
95
96 pub fn cell_by_name(&self, name: &str) -> Option<CellRef<H>> {
98 self.read().cell_by_name(name).map(|id| self.cell(id))
99 }
100}
101
102impl<H: HierarchyEdit> RwRefAccess<H> {
103 pub fn create_cell(&self, name: H::NameType) -> CellRef<H> {
104 let id = self.write().create_cell(name);
105 self.cell(id)
106 }
107
108 pub fn remove_cell(&self, cell: CellRef<H>) {
109 self.write().remove_cell(&cell.id)
110 }
111}
112
113#[derive(Clone)]
116pub struct CellRef<H: HierarchyBase> {
117 pub(super) base: RwRefAccess<H>,
119 pub(super) id: H::CellId,
121}
122
123impl<T: HierarchyBase> Eq for CellRef<T> {}
124
125impl<T: HierarchyBase> PartialEq for CellRef<T> {
126 fn eq(&self, other: &Self) -> bool {
127 self.base == other.base && self.id == other.id
128 }
129}
130
131impl<T: HierarchyBase> Hash for CellRef<T> {
132 fn hash<H: Hasher>(&self, state: &mut H) {
133 self.base.hash(state);
134 self.id.hash(state);
135 }
136}
137
138impl<H: HierarchyBase> CellRef<H> {
139 pub fn base(&self) -> &RwRefAccess<H> {
141 &self.base
142 }
143
144 pub fn id(&self) -> H::CellId {
146 self.id.clone()
147 }
148
149 pub fn name(&self) -> H::NameType {
151 self.base.read().cell_name(&self.id)
152 }
153
154 pub fn each_cell_instance_id(&self) -> Vec<H::CellInstId> {
156 self.base.read().each_cell_instance_vec(&self.id)
157 }
158
159 pub fn each_cell_instance(&self) -> Vec<CellInstRef<H>> {
161 self.base
162 .read()
163 .each_cell_instance(&self.id)
164 .map(move |id| CellInstRef {
165 base: self.base.clone(),
166 id,
167 })
168 .collect()
169 }
170
171 pub fn cell_instance_by_name(&self, name: &str) -> Option<CellInstRef<H>> {
173 self.base
174 .read()
175 .cell_instance_by_name(&self.id, name)
176 .map(|id| CellInstRef {
177 base: self.base.clone(),
178 id,
179 })
180 }
181
182 pub fn each_reference_id(&self) -> Vec<H::CellInstId> {
184 self.base.read().each_cell_reference_vec(&self.id)
185 }
186
187 pub fn each_reference(&self) -> Vec<CellInstRef<H>> {
189 self.base
190 .read()
191 .each_cell_reference(&self.id)
192 .map(|id| CellInstRef {
193 base: self.base.clone(),
194 id,
195 })
196 .collect()
197 }
198
199 pub fn each_cell_dependency(&self) -> Vec<CellRef<H>> {
201 self.base
202 .read()
203 .each_cell_dependency(&self.id)
204 .map(|id| CellRef {
205 base: self.base.clone(),
206 id,
207 })
208 .collect()
209 }
210
211 pub fn each_dependent_cell(&self) -> Vec<CellRef<H>> {
213 self.base
214 .read()
215 .each_dependent_cell(&self.id)
216 .map(|id| CellRef {
217 base: self.base.clone(),
218 id,
219 })
220 .collect()
221 }
222
223 pub fn num_child_instances(&self) -> usize {
225 self.base.read().num_child_instances(&self.id)
226 }
227}
228
229impl<H: HierarchyEdit> CellRef<H> {
230 pub fn create_instance(
231 &self,
232 template: &CellRef<H>,
233 name: Option<H::NameType>,
234 ) -> CellInstRef<H> {
235 let id = self
236 .base
237 .write()
238 .create_cell_instance(&self.id, &template.id, name);
239 self.base.cell_inst(id)
240 }
241
242 pub fn remove_instance(&self, inst: CellInstRef<H>) {
243 self.base.write().remove_cell_instance(&inst.id);
244 }
245}
246
247#[derive(Clone, Hash)]
250pub struct CellInstRef<H: HierarchyBase> {
251 pub(super) base: RwRefAccess<H>,
253 pub(super) id: H::CellInstId,
255}
256
257impl<T: HierarchyBase> Eq for CellInstRef<T> {}
258
259impl<T: HierarchyBase> PartialEq for CellInstRef<T> {
260 fn eq(&self, other: &Self) -> bool {
261 self.base == other.base && self.id == other.id
262 }
263}
264
265impl<H: HierarchyBase> CellInstRef<H> {
266 pub fn base(&self) -> &RwRefAccess<H> {
268 &self.base
269 }
270
271 pub fn id(&self) -> H::CellInstId {
273 self.id.clone()
274 }
275
276 pub fn name(&self) -> Option<H::NameType> {
278 self.base.read().cell_instance_name(&self.id)
279 }
280
281 pub fn parent(&self) -> CellRef<H> {
283 CellRef {
284 base: self.base.clone(),
285 id: self.parent_id(),
286 }
287 }
288
289 pub fn template(&self) -> CellRef<H> {
291 CellRef {
292 base: self.base.clone(),
293 id: self.template_id(),
294 }
295 }
296
297 pub fn parent_id(&self) -> H::CellId {
299 self.base.read().parent_cell(&self.id)
300 }
301
302 pub fn template_id(&self) -> H::CellId {
304 self.base.read().template_cell(&self.id)
305 }
306}
307
308#[cfg(test)]
309mod tests {
310 use crate::chip::Chip;
311 use crate::prelude::*;
312 use crate::rw_reference_access::RwRefAccess;
313 use std::collections::hash_map::DefaultHasher;
314 use std::hash::{Hash, Hasher};
315
316 fn create_test_chip() -> RwRefAccess<Chip> {
318 let mut chip = Chip::new();
319 let top = chip.create_cell("TOP".into());
320 let sub = chip.create_cell("SUB".into());
321 let _inst1 = chip.create_cell_instance(&top, &sub, Some("inst1".into()));
322 RwRefAccess::new(chip)
323 }
324
325 #[test]
326 fn create_rw_refaccess_from_mutable_reference() {
327 let mut chip = Chip::new();
328 let _rw_chip = RwRefAccess::new(&mut chip);
329 }
331
332 fn hash<T: Hash>(t: &T) -> u64 {
333 let mut s = DefaultHasher::new();
334 t.hash(&mut s);
335 s.finish()
336 }
337
338 #[test]
339 fn test_find_cell_by_name() {
340 let chip = create_test_chip();
341 let _top = chip.cell_by_name("TOP").unwrap();
342 let _sub = chip.cell_by_name("SUB").unwrap();
343 }
344
345 #[test]
346 fn test_find_cell_instance_by_name() {
347 let chip = create_test_chip();
348 let top = chip.cell_by_name("TOP").unwrap();
349 let _inst1 = top.cell_instance_by_name("inst1").unwrap();
350 }
351
352 #[test]
353 fn test_cell_equality() {
354 let chip = create_test_chip();
355 let top = chip.cell_by_name("TOP").unwrap();
356 let sub = chip.cell_by_name("SUB").unwrap();
357 assert!(top == top.clone());
358 assert!(top != sub);
359 }
360
361 #[test]
362 fn test_cell_hash() {
363 let chip = create_test_chip();
364 let top = chip.cell_by_name("TOP").unwrap();
365 let sub = chip.cell_by_name("SUB").unwrap();
366 assert_eq!(hash(&top), hash(&top.clone()));
367 assert_eq!(hash(&sub), hash(&sub.clone()));
368 assert_ne!(hash(&top), hash(&sub)); }
370
371 #[test]
372 fn test_cell_instance_equality() {
373 let chip = create_test_chip();
374 let top = chip.cell_by_name("TOP").unwrap();
375 let sub = chip.cell_by_name("SUB").unwrap();
376 let inst1 = top.cell_instance_by_name("inst1").unwrap();
377 let inst2 = top.create_instance(&sub, Some("inst2".into()));
378 assert!(inst1 == inst1.clone());
379 assert!(inst1 != inst2);
380 }
381
382 #[test]
383 fn test_create_cell() {
384 let chip = create_test_chip();
385 chip.create_cell("NEW".into());
386 chip.cell_by_name("NEW").unwrap();
387 }
388
389 #[test]
390 fn test_create_instance() {
391 let chip = create_test_chip();
392 let top = chip.cell_by_name("TOP").unwrap();
393 let sub = chip.cell_by_name("SUB").unwrap();
394 let inst = top.create_instance(&sub, Some("inst2".into()));
395 assert!(inst.template() == sub);
396 assert!(inst.parent() == top);
397 }
398
399 #[test]
400 fn test_access_child_instances() {
401 let chip = create_test_chip();
402 let top = chip.cell_by_name("TOP").unwrap();
403 let children = top.each_cell_instance();
404 assert_eq!(children.len(), 1);
405 }
406
407 #[test]
408 fn test_cell_dependencies() {
409 let chip = create_test_chip();
410 let top = chip.cell_by_name("TOP").unwrap();
411 let sub = chip.cell_by_name("SUB").unwrap();
412 assert_eq!(top.each_cell_dependency().len(), 1);
413 assert_eq!(sub.each_cell_dependency().len(), 0);
414 }
415
416 #[test]
417 fn test_dependent_cells() {
418 let chip = create_test_chip();
419 let top = chip.cell_by_name("TOP").unwrap();
420 let sub = chip.cell_by_name("SUB").unwrap();
421 assert_eq!(top.each_dependent_cell().len(), 0);
422 assert_eq!(sub.each_dependent_cell().len(), 1);
423 }
424}