1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//! PCB class definitions for organizing objects.
//!
//! Classes group related objects (components, nets, pads, etc.) for
//! design rules, visibility control, and organization.
use crate::types::ParameterCollection;
/// The kind/type of class.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum ClassKind {
/// Net class - groups nets for routing rules.
#[default]
Net = 0,
/// Component class - groups components.
Component = 1,
/// From-To class - groups from-to pairs.
FromTo = 2,
/// Pad class - groups pads.
Pad = 3,
/// Layer class - groups layers.
Layer = 4,
/// Differential pair class.
DifferentialPair = 5,
/// Design channel class.
DesignChannel = 6,
/// Polygon class - groups polygons.
Polygon = 7,
/// Structure class.
Structure = 8,
/// Unknown class kind.
Unknown(u8),
}
impl ClassKind {
/// Create from integer value.
pub fn from_int(value: i32) -> Self {
match value {
0 => ClassKind::Net,
1 => ClassKind::Component,
2 => ClassKind::FromTo,
3 => ClassKind::Pad,
4 => ClassKind::Layer,
5 => ClassKind::DifferentialPair,
6 => ClassKind::DesignChannel,
7 => ClassKind::Polygon,
8 => ClassKind::Structure,
v => ClassKind::Unknown(v as u8),
}
}
/// Convert to integer value.
pub fn to_int(self) -> i32 {
match self {
ClassKind::Net => 0,
ClassKind::Component => 1,
ClassKind::FromTo => 2,
ClassKind::Pad => 3,
ClassKind::Layer => 4,
ClassKind::DifferentialPair => 5,
ClassKind::DesignChannel => 6,
ClassKind::Polygon => 7,
ClassKind::Structure => 8,
ClassKind::Unknown(v) => v as i32,
}
}
}
/// A PCB class definition.
///
/// Classes are used to group related objects (nets, components, pads, etc.)
/// for applying design rules, visibility settings, or organization.
#[derive(Debug, Clone, Default)]
pub struct PcbClass {
/// Class name.
pub name: String,
/// The kind of class (Net, Component, Pad, etc.).
pub kind: ClassKind,
/// Whether this is a superclass (contains all objects of this kind).
pub superclass: bool,
/// Whether this class was auto-generated.
pub auto_generated: bool,
/// Kind of auto-generation (0=none, 1=bottom side, 2=top side).
pub auto_generated_kind: i32,
/// Whether this is a schematic auto-generated cluster.
pub sch_auto_generated_cluster: bool,
/// Unique ID for the class.
pub unique_id: String,
/// Whether the class is selected.
pub selected: bool,
/// All parameters (for round-tripping unknown fields).
pub params: ParameterCollection,
}
impl PcbClass {
/// Create a new class with the given name and kind.
pub fn new(name: &str, kind: ClassKind) -> Self {
Self {
name: name.to_string(),
kind,
..Default::default()
}
}
/// Parse a class from parameters.
pub fn from_params(params: &ParameterCollection) -> Self {
Self {
name: params
.get("NAME")
.map(|v| v.as_str().to_string())
.unwrap_or_default(),
kind: params
.get("KIND")
.map(|v| ClassKind::from_int(v.as_int_or(0)))
.unwrap_or_default(),
superclass: params
.get("SUPERCLASS")
.map(|v| v.as_bool_or(false))
.unwrap_or(false),
auto_generated: params
.get("AUTOGENERATEDCLASS")
.map(|v| v.as_bool_or(false))
.unwrap_or(false),
auto_generated_kind: params
.get("AUTOGENERATEDCLASSKIND")
.map(|v| v.as_int_or(0))
.unwrap_or(0),
sch_auto_generated_cluster: params
.get("SCHAUTOGENERATEDCLUSTER")
.map(|v| v.as_bool_or(false))
.unwrap_or(false),
unique_id: params
.get("UNIQUEID")
.map(|v| v.as_str().to_string())
.unwrap_or_default(),
selected: params
.get("SELECTED")
.map(|v| v.as_bool_or(false))
.unwrap_or(false),
params: params.clone(),
}
}
/// Export to parameters.
pub fn to_params(&self) -> ParameterCollection {
let mut params = self.params.clone();
params.add("NAME", &self.name);
params.add_int("KIND", self.kind.to_int());
params.add("SUPERCLASS", if self.superclass { "TRUE" } else { "FALSE" });
params.add(
"AUTOGENERATEDCLASS",
if self.auto_generated { "TRUE" } else { "FALSE" },
);
if self.auto_generated_kind != 0 {
params.add_int("AUTOGENERATEDCLASSKIND", self.auto_generated_kind);
}
params.add(
"SCHAUTOGENERATEDCLUSTER",
if self.sch_auto_generated_cluster {
"TRUE"
} else {
"FALSE"
},
);
if !self.unique_id.is_empty() {
params.add("UNIQUEID", &self.unique_id);
}
params.add("SELECTED", if self.selected { "TRUE" } else { "FALSE" });
params
}
}