1use std::{fs::OpenOptions, io::{BufWriter, Write}, path::Path};
2
3use crate::{error::{LibError, LibErrorContext}, model::{LibCell, LibGroup, LibLibrary, LibPin, LibValue}};
4
5pub trait IntoLibGroup {
6 fn into_group(self) -> LibGroup;
7}
8
9impl IntoLibGroup for LibLibrary {
10 fn into_group(self) -> LibGroup {
11 let mut groups = self.groups;
12 for cell in self.cells {
13 let cell_group = cell.into_group();
14 groups.push(cell_group);
15 }
16
17 LibGroup {
18 kind: "library".to_string(),
19 params: vec![self.name],
20 attrs: self.attrs,
21 groups,
22 }
23 }
24}
25
26impl IntoLibGroup for LibCell {
27 fn into_group(self) -> LibGroup {
28 let mut groups = self.groups;
29 for pin in self.pins {
30 let pin_group = pin.into_group();
31 groups.push(pin_group);
32 }
33
34 LibGroup {
35 kind: "cell".to_string(),
36 params: vec![self.name],
37 attrs: self.attrs,
38 groups,
39 }
40 }
41}
42
43impl IntoLibGroup for LibPin {
44 fn into_group(self) -> LibGroup {
45 let mut attrs = self.attrs;
46 if let Some(function) = self.function {
47 attrs.insert("function".to_string(), LibValue::String(function.to_string()));
48 }
49
50 LibGroup {
51 kind: "pin".to_string(),
52 params: vec![self.name],
53 attrs,
54 groups: self.groups
55 }
56 }
57}
58
59impl LibGroup {
60 pub fn save_file<P: AsRef<Path>>(&self, path: P) -> Result<(), LibError> {
61 let file = OpenOptions::new()
62 .create(true)
63 .open(path).map_err(|e| LibError::Io(e))
64 .context(|| "create file")?;
65 let mut writer = BufWriter::new(file);
66
67 self.write_to_file_ident(&mut writer, 0)
68 }
69
70 fn write_to_file_ident<W: Write>(&self, writer: &mut W, ident: usize) -> Result<(), LibError> {
71 fn write_with_ident<W: Write>(writer: &mut W, ident: usize, add_ident: usize, context: &str) -> Result<(), LibError> {
72 for _ in 0..ident + add_ident {
73 writer.write_all(b" ")?;
74 }
75 writer.write_all(context.as_bytes())?;
76 writer.write_all(b"\n")?;
77 Ok(())
78 }
79
80 write_with_ident(writer, ident, 0, &format!("{}({}) {{", self.kind, self.params.join(", ")))?;
82
83 for (key, value) in self.attrs.iter() {
85 if value.is_complex() {
86 write_with_ident(writer, ident, 1, &format!("{} {};", key, value))?;
87 } else {
88 write_with_ident(writer, ident, 1, &format!("{}: {};", key, value))?;
89 }
90 }
91
92 for group in self.groups.iter() {
94 group.write_to_file_ident(writer, ident + 1)?;
95 }
96
97 write_with_ident(writer, ident, 0, "}")?;
99
100 Ok(())
101 }
102}
103
104#[cfg(test)]
105mod test {
106 #[test]
107 fn test_save_file() {
108
109 }
110}