libreda_db/layout/
util.rs

1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Utility functions for dealing with layouts.
7
8use crate::traits::{LayoutBase, LayoutEdit};
9use iron_shapes::CoordinateType;
10use std::borrow::Borrow;
11
12/// Copy the shapes on a specific layer from one cell into another cell.
13pub fn copy_shapes<LS, LT, C>(
14    target_layout: &mut LT,
15    target_cell: &LT::CellId,
16    target_layer: &LT::LayerId,
17    source_layout: &LS,
18    source_cell: &LS::CellId,
19    source_layer: &LS::LayerId,
20) where
21    C: CoordinateType,
22    LS: LayoutBase<Coord = C>,
23    LT: LayoutEdit<Coord = C>,
24{
25    source_layout.for_each_shape(source_cell, source_layer, |_, g| {
26        let g2 = g.clone();
27        target_layout.insert_shape(target_cell, target_layer, g2);
28    })
29}
30
31/// Copy the shapes from all layers in a cell into another cell.
32pub fn copy_shapes_all_layers<LS, LT, C>(
33    target_layout: &mut LT,
34    target_cell: &LT::CellId,
35    source_layout: &LS,
36    source_cell: &LS::CellId,
37) where
38    C: CoordinateType,
39    LS: LayoutBase<Coord = C>,
40    LT: LayoutEdit<Coord = C>,
41{
42    for source_layer in source_layout.each_layer() {
43        // Find or create layer in target layout based on layer number or name.
44        let layer_info = source_layout.layer_info(&source_layer);
45        let target_layer =
46            target_layout.find_or_create_layer(layer_info.index, layer_info.datatype);
47        copy_shapes(
48            target_layout,
49            target_cell,
50            &target_layer,
51            source_layout,
52            source_cell,
53            &source_layer,
54        )
55    }
56}
57
58/// Copy all layers (without their contents) from a source layout into a destination layout.
59/// # Panics
60/// Panics if a layer number or layer name already exists.
61pub fn copy_all_layers<LS, LT>(target_layout: &mut LT, source_layout: &LS)
62where
63    LS: LayoutBase,
64    LT: LayoutEdit,
65{
66    for l in source_layout.each_layer() {
67        copy_layer(target_layout, source_layout, &l);
68    }
69}
70
71/// Copy all layers (without their contents) from a source layout into a destination layout and preserve
72/// the layer IDs.
73/// Source and target layout must have the same `LayerId` type.
74///
75/// # Panics
76/// Panics if a layer number or layer name already exists.
77pub fn copy_all_layers_preserve_ids<LS, LT>(target_layout: &mut LT, source_layout: &LS)
78where
79    LS: LayoutBase,
80    LT: LayoutEdit<LayerId = LS::LayerId>,
81{
82    for l in source_layout.each_layer() {
83        copy_layer_preserve_id(target_layout, source_layout, &l);
84    }
85}
86
87/// Copy a layer (without its content) from a source layout into a destination layout.
88///
89/// # Panics
90/// Panics if the layer number or layer name already exists.
91pub fn copy_layer<LS, LT>(
92    target_layout: &mut LT,
93    source_layout: &LS,
94    source_layer: &LS::LayerId,
95) -> LT::LayerId
96where
97    LS: LayoutBase,
98    LT: LayoutEdit,
99{
100    let layer_info = source_layout.layer_info(source_layer);
101    let layer_id = target_layout.create_layer(layer_info.index, layer_info.datatype);
102
103    // Convert between the name types via `&str`.
104    let layer_name = layer_info.name.as_ref().map(|n| {
105        let s: &str = n.borrow();
106        s.to_string().into()
107    });
108
109    target_layout.set_layer_name(&layer_id, layer_name);
110
111    layer_id
112}
113
114/// Copy a layer (without its content) from a source layout into a destination layout
115/// while preserving the layer ID.
116/// `LayerId` types of the both layouts must be the same.
117///
118/// # Panics
119/// Panics if the layer number or layer name already exists.
120pub fn copy_layer_preserve_id<LS, LT>(
121    target_layout: &mut LT,
122    source_layout: &LS,
123    source_layer: &LS::LayerId,
124) -> LT::LayerId
125where
126    LS: LayoutBase,
127    LT: LayoutEdit<LayerId = LS::LayerId>,
128{
129    let layer_info = source_layout.layer_info(source_layer);
130    let layer_id = source_layer.clone();
131    target_layout
132        .create_layer_with_id(layer_id.clone(), layer_info.index, layer_info.datatype)
133        .expect("layer already exists");
134
135    // Convert between the name types via `&str`.
136    let layer_name = layer_info.name.as_ref().map(|n| {
137        let s: &str = n.borrow();
138        s.to_string().into()
139    });
140
141    target_layout.set_layer_name(&layer_id, layer_name);
142
143    layer_id
144}
145
146/// Helper functions for layouts.
147///
148/// This trait is automatically implemented for all types which implement [`trait@LayoutEdit`].
149pub trait LayoutEditUtil: LayoutEdit {
150    /// Create a layer or return an existing one.
151    fn find_or_create_layer(&mut self, index: u32, datatype: u32) -> Self::LayerId {
152        self.find_layer(index, datatype)
153            .unwrap_or_else(|| self.create_layer(index, datatype))
154    }
155}
156
157impl<L: LayoutEdit> LayoutEditUtil for L {}