consortium_data/database.rs
1// Copyright 2026 Ethan Wu
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17//! Chip-family databases, embedded at compile time and resolved from a chip
18//! part number declared in `[profile] chip`.
19
20pub use consortium_cfg_common::database::*;
21
22use crate::error::DataError;
23
24/// A chip-family database bundled into the binary, paired with the part-number
25/// prefix that selects it.
26struct Embedded {
27 /// Lowercase part-number prefix that selects this family (e.g. `stm32mp25`).
28 prefix: &'static str,
29 /// The raw YAML definition.
30 yaml: &'static str,
31}
32
33/// All bundled chip-family databases.
34///
35/// Ordered most-specific prefix first so that, for example, `stm32mp25` is
36/// preferred over a hypothetical shorter `stm32mp` prefix.
37const DATABASES: &[Embedded] = &[
38 Embedded {
39 prefix: "stm32mp25",
40 yaml: include_str!("../database/memory/stm32mp25.yaml"),
41 },
42 Embedded {
43 prefix: "stm32mp23",
44 yaml: include_str!("../database/memory/stm32mp23.yaml"),
45 },
46 Embedded {
47 prefix: "stm32mp21",
48 yaml: include_str!("../database/memory/stm32mp21.yaml"),
49 },
50 Embedded {
51 prefix: "mimx95",
52 yaml: include_str!("../database/memory/mimx95.yaml"),
53 },
54 Embedded {
55 prefix: "mimx93",
56 yaml: include_str!("../database/memory/mimx93.yaml"),
57 },
58];
59
60/// Resolves and parses the chip-family database for a chip part number.
61///
62/// The lookup is a case-insensitive prefix match: `stm32mp257fak3` resolves to
63/// the `stm32mp25` family. Common i.MX aliases (`imx95`, `imx93`) are accepted
64/// in addition to the canonical `mimx*` names.
65///
66/// # Errors
67///
68/// Returns [`DataError::UnknownChip`] if no family matches, or
69/// [`DataError::DatabaseParse`] if the bundled YAML fails to deserialize.
70pub fn load(chip: &str) -> Result<ChipDatabase, DataError> {
71 let needle = normalize(chip);
72 let entry = DATABASES
73 .iter()
74 .find(|entry| needle.starts_with(entry.prefix))
75 .ok_or_else(|| DataError::UnknownChip(chip.to_string()))?;
76
77 serde_yaml::from_str(entry.yaml)
78 .map_err(|err| DataError::DatabaseParse(chip.to_string(), err.to_string()))
79}
80
81/// Lowercases the part number and rewrites `imx` aliases to the `mimx`
82/// database prefix.
83fn normalize(chip: &str) -> String {
84 let lowered = chip.to_ascii_lowercase();
85 match lowered.strip_prefix("imx") {
86 Some(rest) => format!("mimx{rest}"),
87 None => lowered,
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn resolves_stm32mp25_from_full_part_number() {
97 let database = load("stm32mp257fak3").expect("stm32mp25 family should resolve");
98 assert_eq!(database.name, "STM32MP25");
99 }
100
101 #[test]
102 fn accepts_imx_alias() {
103 assert!(load("imx95").is_ok());
104 }
105
106 #[test]
107 fn rejects_unknown_chip() {
108 assert!(matches!(load("acme9000"), Err(DataError::UnknownChip(_))));
109 }
110}