Skip to main content

type_bridge_schema_codegen/
package.rs

1use std::collections::BTreeMap;
2
3use type_bridge_contract::diagnostic::Diagnostic;
4
5use crate::invalid;
6
7/// An ordered in-memory package with normalized relative paths.
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct GeneratedPackage {
10    files: BTreeMap<String, Vec<u8>>,
11}
12
13impl GeneratedPackage {
14    pub(crate) fn try_new(
15        files: impl IntoIterator<Item = (String, Vec<u8>)>,
16    ) -> Result<Self, Diagnostic> {
17        let mut ordered = BTreeMap::new();
18        for (path, bytes) in files {
19            if path.is_empty()
20                || path.starts_with('/')
21                || path.contains('\\')
22                || path.contains('\0')
23                || path
24                    .split('/')
25                    .any(|part| part.is_empty() || matches!(part, "." | ".."))
26            {
27                return Err(invalid(
28                    "invalid_generated_package_path",
29                    "generated package paths must be normalized relative paths",
30                ));
31            }
32            if ordered.insert(path, bytes).is_some() {
33                return Err(invalid(
34                    "duplicate_generated_package_path",
35                    "a generated package path may be emitted only once",
36                ));
37            }
38        }
39        Ok(Self { files: ordered })
40    }
41
42    /// Return files in bytewise path order.
43    #[must_use]
44    pub const fn files(&self) -> &BTreeMap<String, Vec<u8>> {
45        &self.files
46    }
47
48    /// Borrow one generated file.
49    #[must_use]
50    pub fn get(&self, path: &str) -> Option<&[u8]> {
51        self.files.get(path).map(Vec::as_slice)
52    }
53}