Skip to main content

burn_central_core/bundle/
core.rs

1use serde::{Serialize, de::DeserializeOwned};
2use std::io::Read;
3
4/// Trait for encoding data into a bundle of files
5pub trait BundleEncode {
6    type Settings: Default + Serialize + DeserializeOwned;
7    type Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>;
8
9    fn encode<O: BundleSink>(
10        self,
11        sink: &mut O,
12        settings: &Self::Settings,
13    ) -> Result<(), Self::Error>;
14}
15
16/// Trait for decoding data from a bundle of files
17pub trait BundleDecode: Sized {
18    type Settings: Default + Serialize + DeserializeOwned;
19    type Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>;
20
21    fn decode<I: BundleSource>(source: &I, settings: &Self::Settings) -> Result<Self, Self::Error>;
22}
23
24/// Trait for writing files to a bundle
25pub trait BundleSink {
26    /// Add a file by streaming its bytes. Returns computed checksum + size.
27    fn put_file<R: Read>(&mut self, path: &str, reader: &mut R) -> Result<(), String>;
28
29    /// Convenience: write all bytes.
30    fn put_bytes(&mut self, path: &str, bytes: &[u8]) -> Result<(), String> {
31        let mut r = std::io::Cursor::new(bytes);
32        self.put_file(path, &mut r)
33    }
34}
35
36/// Trait for reading files from a bundle
37pub trait BundleSource {
38    /// Open the given path for streaming read. Must validate existence.
39    fn open(&self, path: &str) -> Result<Box<dyn Read + Send>, String>;
40
41    /// Optionally list available files (used by generic decoders; can be best-effort).
42    fn list(&self) -> Result<Vec<String>, String>;
43}
44
45/// Normalize a path within a bundle (use forward slashes, remove leading slash)
46pub fn normalize_bundle_path<S: AsRef<str>>(s: S) -> String {
47    s.as_ref()
48        .replace('\\', "/")
49        .trim_start_matches('/')
50        .to_string()
51}