reda_lib/io/write/
mod.rs

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));
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        // kind(params) {
81        write_with_ident(writer, ident, 0, &format!("{}({}) {{", self.kind, self.params.join(", ")))?;
82        
83        // attr
84        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        // groups, recursive call
93        for group in self.groups.iter() {
94            group.write_to_file_ident(writer, ident + 1)?;
95        }
96
97        // }
98        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}