1use crate::board::BoardPanel;
17use crate::library::Library;
18
19pub mod board;
20pub mod component_placement;
21pub mod components;
22pub mod drilled_holes;
23pub mod headers;
24pub mod library;
25pub mod notes;
26pub mod outlines;
27pub mod point;
28pub mod primitives;
29mod validation;
30
31pub fn parse_board_file(file_path: &str) -> Result<BoardPanel, String> {
33 if !file_path.ends_with(".emn") {
34 return Err("Board and panel files must end with .emn.".to_string());
35 }
36 let file = std::fs::read_to_string(file_path).map_err(|e| e.to_string())?;
37 let result = board::parse_board_or_panel(&file);
38
39 match result {
40 Ok(board) => Ok(board),
41 Err(e) => Err(format!("Failed to parse board file: {}", e)),
42 }
43}
44
45pub fn parse_library_file(file_path: &str) -> Result<Library, String> {
47 if !file_path.ends_with(".emp") {
48 return Err("Library files must end with .emp.".to_string());
49 }
50
51 let file = std::fs::read_to_string(file_path).map_err(|e| e.to_string())?;
52 let result = library::parse_library(&file);
53
54 match result {
55 Ok(library) => Ok(library),
56 Err(e) => Err(format!("Failed to parse library file: {}", e)),
57 }
58}
59
60fn parse_assembly(
66 panel_file: Option<&str>,
67 library_file: &str,
68 board_files: Vec<&str>,
69) -> Result<(Option<BoardPanel>, Library, Vec<BoardPanel>), String> {
70 let mut boards = Vec::new();
71
72 let panel = match panel_file {
73 Some(file) => Some(parse_board_file(file)?),
74 None => None,
75 };
76
77 let library = parse_library_file(library_file)?;
78
79 for board_file in board_files {
80 boards.push(parse_board_file(board_file)?);
81 }
82
83 for board in &boards {
84 validation::library_references_valid(&library, board)?;
85 }
86
87 if let Some(panel) = &panel {
88 validation::panel_references_valid(panel, &boards)?;
89 }
90
91 Ok((panel, library, boards))
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_parse_spec_board_file() {
100 parse_board_file("src/test_files/board.emn").unwrap();
101 }
102 #[test]
103 fn test_parse_isol_board_file() {
104 parse_board_file("src/test_files/ISOL.emn").unwrap();
105 }
106
107 #[test]
108 fn test_parse_beaglebone_board_file() {
109 parse_board_file("src/test_files/beaglebone.emn").unwrap();
110 }
111
112 #[test]
113 fn test_parse_ain_board_file() {
114 parse_board_file("src/test_files/ain.emn").unwrap();
115 }
116
117 #[test]
118 fn test_parse_esp_board_file() {
119 parse_board_file("src/test_files/esp.emn").unwrap();
120 }
121
122 #[test]
123 fn test_parse_library_file() {
124 parse_library_file("src/test_files/library.emp").unwrap();
125 }
126 #[test]
127 fn test_parse_isol_library_file() {
128 parse_library_file("src/test_files/ISOL.emp").unwrap();
129 }
130
131 #[test]
132 fn test_parse_beaglebone_library_file() {
133 parse_library_file("src/test_files/beaglebone.emp").unwrap();
134 }
135
136 #[test]
137 fn test_parse_ain_library_file() {
138 parse_library_file("src/test_files/ain.emp").unwrap();
139 }
140
141 #[test]
142 fn test_parse_esp_library_file() {
143 parse_library_file("src/test_files/esp.emp").unwrap();
144 }
145
146 #[test]
147 fn test_parse_assembly() {
148 let panel = Some("src/test_files/panel.emn");
149 let library = "src/test_files/library.emp";
150 let boards = vec!["src/test_files/board.emn"];
151
152 let result = parse_assembly(panel, library, boards.clone());
153 assert!(result.is_ok());
154
155 let invalid_panel = Some("src/test_files/invalid_panel.emn");
157
158 let result = parse_assembly(invalid_panel, library, boards);
159 assert!(result.is_err());
160 }
161}