1use std::{fs::File, path::Path};
2use crate::{GdsAref, GdsBoundary, GdsBox, GdsLibrary, GdsNode, GdsPath, GdsSref, GdsStructure, GdsText};
3
4use super::GdsWriteResult;
5
6pub struct TextWriter<W> {
7 writer: W,
8}
9
10impl TextWriter<File> {
11 pub fn open<P: AsRef<Path>>(path: P) -> GdsWriteResult<Self> {
12 let file = File::create(path)?;
13 Ok(Self { writer: file })
14 }
15}
16
17impl<W: std::io::Write> TextWriter<W> {
18 pub fn new(writer: W) -> Self {
19 Self { writer }
20 }
21}
22
23impl<W: std::io::Write> TextWriter<W> {
24 pub fn write(&mut self, layout: &GdsLibrary) -> GdsWriteResult<()> {
25 let indent = 0;
26 self.write_indent(indent)?;
27 writeln!(self.writer, "GDSII Layout Object")?;
28
29 let attr_indent = indent + 1;
30
31 self.write_indent(attr_indent)?;
32 writeln!(self.writer, "version: {}", layout.version)?;
33
34 self.write_indent(attr_indent)?;
35 writeln!(self.writer, "library name: {}", layout.name)?;
36
37 self.write_indent(attr_indent)?;
38 writeln!(self.writer, "units: ({}, {})", layout.usrunits_per_dbunit, layout.meters_per_dbunit)?;
39
40 self.write_indent(attr_indent)?;
41 writeln!(self.writer, "create date: {}", layout.create_date.to_string())?;
42
43 self.write_indent(attr_indent)?;
44 writeln!(self.writer, "modify date: {}", layout.modify_date.to_string())?;
45
46 for (_key, structure) in &layout.structures {
47 self.write_structure(&structure.read().unwrap(), attr_indent)?;
48 }
49
50 Ok(())
51 }
52}
53
54
55impl<W: std::io::Write> TextWriter<W> {
56 pub fn write_structure(&mut self, structure: &GdsStructure, indent: usize) -> GdsWriteResult<()> {
57 self.write_indent(indent)?;
58 writeln!(self.writer, "Structure:")?;
59
60 let attr_indent = indent + 1;
61
62 self.write_indent(attr_indent)?;
63 writeln!(self.writer, "name: {}", structure.name)?;
64
65 self.write_indent(attr_indent)?;
66 writeln!(self.writer, "create date: {}", structure.create_date.to_string())?;
67
68 self.write_indent(attr_indent)?;
69 writeln!(self.writer, "modify date: {}", structure.modify_date.to_string())?;
70
71 for e in &structure.boundarys {
72 self.write_boundary(e, attr_indent)?;
73 }
74
75 for e in &structure.paths {
76 self.write_path(e, attr_indent)?;
77 }
78
79 for e in &structure.srefs {
80 self.write_sref(e, attr_indent)?;
81 }
82
83 for e in &structure.arefs {
84 self.write_aref(e, attr_indent)?;
85 }
86
87 for e in &structure.texts {
88 self.write_text(e, attr_indent)?;
89 }
90
91 for e in &structure.nodes {
92 self.write_node(e, attr_indent)?;
93 }
94
95 for e in &structure.boxes {
96 self.write_box(e, attr_indent)?;
97 }
98
99 Ok(())
100 }
101}
102
103
104impl<W: std::io::Write> TextWriter<W> {
105 pub fn write_boundary(&mut self, boundary: &GdsBoundary, indent: usize) -> GdsWriteResult<()> {
106 self.write_indent(indent)?;
107 writeln!(self.writer, "Boundary Element")?;
108
109 let attr_indent = indent + 1;
110
111 if let Some(flags) = boundary.elf_flags {
112 self.write_indent(attr_indent)?;
113 writeln!(self.writer, "elf_flags: {}", flags)?;
114 }
115
116 if let Some(plex) = boundary.plex {
117 self.write_indent(attr_indent)?;
118 writeln!(self.writer, "plex: {}", plex)?;
119 }
120
121 self.write_indent(attr_indent)?;
122 writeln!(self.writer, "layer: {}", boundary.layer)?;
123
124 self.write_indent(attr_indent)?;
125 writeln!(self.writer, "data_type: {}", boundary.data_type)?;
126
127 self.write_indent(attr_indent)?;
128 write!(self.writer, "xy: [")?;
129 for (i, coord) in boundary.xy.iter().enumerate() {
130 if i > 0 {
131 write!(self.writer, ", ")?;
132 }
133 write!(self.writer, "({}, {})", coord.x, coord.y)?;
134 }
135 writeln!(self.writer, "]")?;
136
137 Ok(())
138 }
139
140 pub fn write_path(&mut self, path: &GdsPath, indent: usize) -> GdsWriteResult<()> {
141 self.write_indent(indent)?;
142 writeln!(self.writer, "Path Element")?;
143
144 let attr_indent = indent + 1;
145
146 if let Some(flags) = path.elf_flags {
147 self.write_indent(attr_indent)?;
148 writeln!(self.writer, "elf_flags: {}", flags)?;
149 }
150
151 if let Some(plex) = path.plex {
152 self.write_indent(attr_indent)?;
153 writeln!(self.writer, "plex: {}", plex)?;
154 }
155
156 self.write_indent(attr_indent)?;
157 writeln!(self.writer, "layer: {}", path.layer)?;
158
159 if let Some(purpose) = path.purpose_layer {
160 self.write_indent(attr_indent)?;
161 writeln!(self.writer, "purpose layer: {}", purpose)?;
162 }
163
164 self.write_indent(attr_indent)?;
165 writeln!(self.writer, "data_type: {}", path.data_type)?;
166
167 self.write_indent(attr_indent)?;
168 writeln!(self.writer, "path_type: {}", path.path_type)?;
169
170 if let Some(width) = path.width {
171 self.write_indent(attr_indent)?;
172 writeln!(self.writer, "width: {}", width)?;
173 }
174
175 self.write_indent(attr_indent)?;
176 write!(self.writer, "xy: [")?;
177 for (i, coord) in path.xy.iter().enumerate() {
178 if i > 0 {
179 write!(self.writer, ", ")?;
180 }
181 write!(self.writer, "({}, {})", coord.x, coord.y)?;
182 }
183 writeln!(self.writer, "]")?;
184
185 Ok(())
186 }
187
188 pub fn write_sref(&mut self, sref: &GdsSref, indent: usize) -> GdsWriteResult<()> {
189 self.write_indent(indent)?;
190 writeln!(self.writer, "Sref Element")?;
191
192 let attr_indent = indent + 1;
193
194 if let Some(flags) = sref.elf_flags {
195 self.write_indent(attr_indent)?;
196 writeln!(self.writer, "elf_flags: {}", flags)?;
197 }
198
199 if let Some(plex) = sref.plex {
200 self.write_indent(attr_indent)?;
201 writeln!(self.writer, "plex: {}", plex)?;
202 }
203
204 self.write_indent(attr_indent)?;
205 writeln!(self.writer, "s_name: {}", sref.s_name)?;
206
207 if let Some(transform) = &sref.transform {
208 self.write_indent(attr_indent)?;
209 write!(self.writer, "s_trans:")?;
210 if transform.flag.reflect {
211 write!(self.writer, " x_mirror")?;
212 }
213 if transform.flag.absolute_magnification {
214 write!(self.writer, "absolute magnification")?;
215 }
216 if transform.flag.absolute_angle {
217 write!(self.writer, "absolute angle")?;
218 }
219 writeln!(self.writer)?;
220
221 self.write_indent(attr_indent)?;
222 writeln!(self.writer, "mag: {}", transform.magnification())?;
223 self.write_indent(attr_indent)?;
224 writeln!(self.writer, "angle: {}", transform.angle())?;
225 }
226
227 self.write_indent(attr_indent)?;
228 writeln!(self.writer, "coordinate: [{}, {}]", sref.position.x, sref.position.y)?;
229
230 Ok(())
231 }
232
233 pub fn write_aref(&mut self, aref: &GdsAref, indent: usize) -> GdsWriteResult<()> {
234 self.write_indent(indent)?;
235 writeln!(self.writer, "Aref Element")?;
236
237 let attr_indent = indent + 1;
238
239 if let Some(flags) = aref.elf_flags {
240 self.write_indent(attr_indent)?;
241 writeln!(self.writer, "elf_flags: {}", flags)?;
242 }
243
244 if let Some(plex) = aref.plex {
245 self.write_indent(attr_indent)?;
246 writeln!(self.writer, "plex: {}", plex)?;
247 }
248
249 self.write_indent(attr_indent)?;
250 writeln!(self.writer, "s_name: {}", aref.s_name)?;
251
252 if let Some(transform) = &aref.transform {
253 self.write_indent(attr_indent)?;
254 write!(self.writer, "s_trans:")?;
255 if transform.flag.reflect {
256 write!(self.writer, " x_mirror")?;
257 }
258 if transform.flag.absolute_magnification {
259 write!(self.writer, "absolute magnification")?;
260 }
261 if transform.flag.absolute_angle {
262 write!(self.writer, "absolute angle")?;
263 }
264 writeln!(self.writer)?;
265
266 self.write_indent(attr_indent)?;
267 writeln!(self.writer, "mag: {}", transform.magnification())?;
268 self.write_indent(attr_indent)?;
269 writeln!(self.writer, "angle: {}", transform.angle())?;
270 }
271
272 self.write_indent(attr_indent)?;
273 writeln!(self.writer, "col: {}", aref.col)?;
274
275 self.write_indent(attr_indent)?;
276 writeln!(self.writer, "row: {}", aref.row)?;
277
278 self.write_indent(attr_indent)?;
279 writeln!(self.writer, "coordinate: [{}, {}]", aref.position.x, aref.position.y)?;
280
281 Ok(())
282 }
283
284 pub fn write_text(&mut self, text: &GdsText, indent: usize) -> GdsWriteResult<()> {
285 self.write_indent(indent)?;
286 writeln!(self.writer, "Text Element")?;
287
288 let attr_indent = indent + 1;
289
290 if let Some(flags) = text.elf_flags {
291 self.write_indent(attr_indent)?;
292 writeln!(self.writer, "elf_flags: {}", flags)?;
293 }
294
295 if let Some(plex) = text.plex {
296 self.write_indent(attr_indent)?;
297 writeln!(self.writer, "plex: {}", plex)?;
298 }
299
300 self.write_indent(attr_indent)?;
301 writeln!(self.writer, "layer: {}", text.layer)?;
302
303 self.write_indent(attr_indent)?;
304 writeln!(self.writer, "data_type: {}", text.text_type)?;
305
306 if let Some(presentation) = text.presentation {
307 self.write_indent(attr_indent)?;
308 writeln!(self.writer, "presentation: {}", presentation)?;
309 }
310
311 self.write_indent(attr_indent)?;
312 writeln!(self.writer, "path_type: {}", text.path_type)?;
313
314 if let Some(width) = text.width {
315 self.write_indent(attr_indent)?;
316 writeln!(self.writer, "width: {}", width)?;
317 }
318
319 if let Some(transform) = &text.transform {
320 self.write_indent(attr_indent)?;
321 write!(self.writer, "s_trans:")?;
322 if transform.flag.reflect {
323 write!(self.writer, " x_mirror")?;
324 }
325 if transform.flag.absolute_magnification {
326 write!(self.writer, "absolute magnification")?;
327 }
328 if transform.flag.absolute_angle {
329 write!(self.writer, "absolute angle")?;
330 }
331 writeln!(self.writer)?;
332
333 self.write_indent(attr_indent)?;
334 writeln!(self.writer, "mag: {}", transform.magnification())?;
335 self.write_indent(attr_indent)?;
336 writeln!(self.writer, "angle: {}", transform.angle())?;
337 }
338
339 self.write_indent(attr_indent)?;
340 writeln!(self.writer, "coordinate: [{}, {}]", text.position.x, text.position.y)?;
341
342 self.write_indent(attr_indent)?;
343 writeln!(self.writer, "string: {}", text.string)?;
344
345 Ok(())
346 }
347
348 pub fn write_node(&mut self, node: &GdsNode, indent: usize) -> GdsWriteResult<()> {
349 self.write_indent(indent)?;
350 writeln!(self.writer, "Node Element")?;
351
352 let attr_indent = indent + 1;
353
354 if let Some(flags) = node.elf_flags {
355 self.write_indent(attr_indent)?;
356 writeln!(self.writer, "elf_flags: {}", flags)?;
357 }
358
359 if let Some(plex) = node.plex {
360 self.write_indent(attr_indent)?;
361 writeln!(self.writer, "plex: {}", plex)?;
362 }
363
364 self.write_indent(attr_indent)?;
365 writeln!(self.writer, "layer: {}", node.layer)?;
366
367 self.write_indent(attr_indent)?;
368 writeln!(self.writer, "data_type: {}", node.node_type)?;
369
370 self.write_indent(attr_indent)?;
371 write!(self.writer, "xy: [")?;
372 for coord in &node.xy {
373 write!(self.writer, "({}, {}), ", coord.x, coord.y)?;
374 }
375 writeln!(self.writer, "]")?;
376
377 Ok(())
378 }
379
380 pub fn write_box(&mut self, boxx: &GdsBox, indent: usize) -> GdsWriteResult<()> {
381 self.write_indent(indent)?;
382 writeln!(self.writer, "Box Element")?;
383
384 let attr_indent = indent + 1;
385
386 if let Some(flags) = boxx.elf_flags {
387 self.write_indent(attr_indent)?;
388 writeln!(self.writer, "elf_flags: {}", flags)?;
389 }
390
391 if let Some(plex) = boxx.plex {
392 self.write_indent(attr_indent)?;
393 writeln!(self.writer, "plex: {}", plex)?;
394 }
395
396 self.write_indent(attr_indent)?;
397 writeln!(self.writer, "layer: {}", boxx.layer)?;
398
399 self.write_indent(attr_indent)?;
400 writeln!(self.writer, "box_type: {}", boxx.box_type)?;
401
402 self.write_indent(attr_indent)?;
403 write!(self.writer, "xy: [")?;
404 for coord in &boxx.xy {
405 write!(self.writer, "({}, {}), ", coord.x, coord.y)?;
406 }
407 writeln!(self.writer, "]")?;
408
409 Ok(())
410 }
411}
412
413impl<W: std::io::Write> TextWriter<W> {
414 fn write_indent(&mut self, level: usize) -> GdsWriteResult<()> {
415 for _ in 0..level {
416 write!(self.writer, " ")?;
417 }
418 Ok(())
419 }
420}