Skip to main content

espforge_esp32metadata/
lib.rs

1use serde::Deserialize;
2use std::collections::HashMap;
3
4#[derive(Debug, Deserialize, Clone)]
5pub struct Board {
6    pub id: String,
7    pub name: String,
8    #[serde(rename = "gnd_top_left")]
9    pub gnd_top_left: String,
10    #[serde(rename = "gnd_top_right")]
11    pub gnd_top_right: String,
12    #[serde(rename = "gnd_bottom_left")]
13    pub gnd_bottom_left: String,
14    #[serde(rename = "gnd_bottom_right")]
15    pub gnd_bottom_right: String,
16}
17
18#[derive(Debug, Deserialize, Clone)]
19pub struct Chip {
20    pub id: String,
21    #[serde(rename = "wokwi_board_id")]
22    pub wokwi_board_id: String,
23    #[serde(rename = "serial_interface")]
24    pub serial_interface: String,
25    pub max_heap_size: usize,
26}
27
28#[derive(Debug, Deserialize)]
29struct Chips {
30    chip: Vec<Chip>,
31}
32
33#[derive(Debug, Deserialize)]
34struct Boards {
35    board: Vec<Board>,
36}
37
38pub struct BoardDatabase {
39    chips: HashMap<String, Chip>,
40    boards: HashMap<String, Board>,
41}
42
43impl BoardDatabase {
44    pub fn load() -> Self {
45        // Load chips.toml
46        let chips_data = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/chips.toml"));
47        let chips: Chips = toml::from_str(chips_data).expect("Failed to parse chips.toml");
48
49        // Load boards.toml
50        let boards_data = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/boards.toml"));
51        let boards: Boards = toml::from_str(boards_data).expect("Failed to parse boards.toml");
52
53        let chip_map: HashMap<String, Chip> = chips
54            .chip
55            .into_iter()
56            .map(|chip| (chip.id.clone(), chip))
57            .collect();
58
59        let board_map: HashMap<String, Board> = boards
60            .board
61            .into_iter()
62            .map(|board| (board.id.clone(), board))
63            .collect();
64
65        Self {
66            chips: chip_map,
67            boards: board_map,
68        }
69    }
70
71    /// Returns the Wokwi board ID/type (e.g., "board-esp32-devkit-c-v4") for the given chip
72    /// This is the value that should be used in diagram.json's "type" field
73    pub fn wokwi_board(&self, chip_id: &str) -> Option<String> {
74        self.chips
75            .get(chip_id)
76            .map(|chip| chip.wokwi_board_id.clone())
77    }
78
79    /// Returns the human-readable board name for the given chip
80    pub fn board_name(&self, chip_id: &str) -> Option<String> {
81        let board_id = self.wokwi_board(chip_id)?;
82        self.boards.get(&board_id).map(|board| board.name.clone())
83    }
84
85    pub fn gnd_top_left(&self, chip_id: &str) -> Option<String> {
86        let board_id = self.wokwi_board(chip_id)?;
87        self.boards
88            .get(&board_id)
89            .map(|board| board.gnd_top_left.clone())
90    }
91
92    pub fn gnd_top_right(&self, chip_id: &str) -> Option<String> {
93        let board_id = self.wokwi_board(chip_id)?;
94        self.boards
95            .get(&board_id)
96            .map(|board| board.gnd_top_right.clone())
97    }
98
99    pub fn gnd_bottom_left(&self, chip_id: &str) -> Option<String> {
100        let board_id = self.wokwi_board(chip_id)?;
101        self.boards
102            .get(&board_id)
103            .map(|board| board.gnd_bottom_left.clone())
104    }
105
106    pub fn gnd_bottom_right(&self, chip_id: &str) -> Option<String> {
107        let board_id = self.wokwi_board(chip_id)?;
108        self.boards
109            .get(&board_id)
110            .map(|board| board.gnd_bottom_right.clone())
111    }
112
113    pub fn is_valid_chip(&self, chip_id: &str) -> bool {
114        self.chips.contains_key(chip_id)
115    }
116
117    pub fn all_chips(&self) -> Vec<String> {
118        self.chips.keys().cloned().collect()
119    }
120
121    /// Get maximum heap size for a chip
122    pub fn max_heap_size(&self, chip_id: &str) -> Option<usize> {
123        self.chips.get(chip_id).map(|chip| chip.max_heap_size)
124    }
125}