mr_bundle/lib.rs
1//! Library for collecting bundling resources based on a manifest.
2//!
3//! Bundles created with Mr. Bundle are designed to be portable so
4//! that they can be sent to other systems and unpacked there.
5//!
6//! A [`Bundle`] contains a [`Manifest`] as well as any number of arbitrary
7//! opaque resources in the form of [`ResourceBytes`]. The manifest describes
8//! the resources that should be included in the bundle. A Bundle can be
9//! serialized and written to a file.
10//!
11//! With the `fs` feature, the `FileSystemBundler` can be used to work with
12//! bundles on the file system.
13//!
14//! # Example: In-memory bundle
15//!
16//! A basic use of this library would be to create a bundle in-memory.
17//!
18//! ```rust
19//! use std::collections::HashMap;
20//! use serde::{Deserialize, Serialize};
21//! use mr_bundle::{Bundle, Manifest, ResourceIdentifier};
22//!
23//! // Define your manifest
24//! #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
25//! struct MyManifest {
26//! video: String,
27//! audio: String,
28//! }
29//!
30//! // Implement the Manifest trait for MyManifest
31//! impl Manifest for MyManifest {
32//! fn generate_resource_ids(&mut self) -> HashMap<ResourceIdentifier, String> {
33//! [self.video.clone(), self.audio.clone()].into_iter().map(|r| {
34//! (r.clone(), r.clone())
35//! }).collect()
36//! }
37//!
38//! fn resource_ids(&self) -> Vec<ResourceIdentifier> {
39//! [self.video.clone(), self.audio.clone()].into_iter().collect()
40//! }
41//!
42//! fn file_name() -> &'static str {
43//! "example.yaml"
44//! }
45//!
46//! fn bundle_extension() -> &'static str {
47//! "bundle"
48//! }
49//! }
50//!
51//! let bundle = Bundle::new(
52//! MyManifest {
53//! video: "audio_sample".into(),
54//! audio: "video_sample".into(),
55//! },
56//! vec![(
57//! "audio_sample".to_string(), vec![1, 2, 3].into()
58//! ), (
59//! "video_sample".to_string(), vec![44, 54, 23].into()
60//! )]
61//! ).unwrap();
62//!
63//! // Serialize the bundle to a byte vector
64//! let bytes = bundle.pack().unwrap();
65//!
66//! // Then do something with the bytes...
67//! ```
68//!
69//! # Example: Bundle to the file system
70//!
71//!
72//! ```rust,no_run
73//! use std::collections::HashMap;
74//! use serde::{Deserialize, Serialize};
75//! use mr_bundle::{resource_id_for_path, Bundle, FileSystemBundler, Manifest, ResourceIdentifier};
76//!
77//! # #[tokio::main]
78//! # async fn main() {
79//! // Define your manifest
80//! #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
81//! struct MyManifest {
82//! video: String,
83//! audio: String,
84//! }
85//!
86//! // Implement the Manifest trait for MyManifest
87//! impl Manifest for MyManifest {
88//! fn generate_resource_ids(&mut self) -> HashMap<ResourceIdentifier, String> {
89//! let mut out = HashMap::new();
90//!
91//! let audio_id = resource_id_for_path(&self.audio).unwrap_or("audio-id".to_string());
92//! out.insert(audio_id.clone(), self.audio.clone());
93//! self.audio = audio_id;
94//!
95//! let video_id = resource_id_for_path(&self.video).unwrap_or("video-id".to_string());
96//! out.insert(video_id.clone(), self.video.clone());
97//! self.video = video_id;
98//!
99//! out
100//! }
101//!
102//! fn resource_ids(&self) -> Vec<ResourceIdentifier> {
103//! [
104//! resource_id_for_path(&self.audio).unwrap_or("audio-id".to_string()),
105//! resource_id_for_path(&self.video).unwrap_or("video-id".to_string())
106//! ].into_iter().collect()
107//! }
108//!
109//! fn file_name() -> &'static str {
110//! "example.yaml"
111//! }
112//!
113//! fn bundle_extension() -> &'static str {
114//! "bundle"
115//! }
116//! }
117//!
118//! // Create an example manifest, and note that the resource paths would also need to exist.
119//! std::fs::write("./example.yaml", r#"
120//! audio: ./audio-sample.mp3
121//! video: ./video-sample.mp4
122//! "#).unwrap();
123//!
124//! // Then create a bundle using the manifest.
125//! // The resulting bundle will be written to the file system.
126//! FileSystemBundler::bundle_to::<MyManifest>(
127//! "./example.yaml",
128//! "./packaging/example.bundle",
129//! ).await.unwrap();
130//!
131//! // The bundle will now exist on the file system.
132//! assert!(std::fs::exists("./packaging/example.bundle").unwrap());
133//! # }
134//! ```
135//!
136
137#![deny(missing_docs)]
138#![cfg_attr(docsrs, feature(doc_cfg))]
139
140mod bundle;
141pub mod error;
142#[cfg(feature = "fs")]
143#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
144mod fs;
145mod manifest;
146mod pack;
147
148pub use bundle::{resource::ResourceBytes, Bundle, ResourceMap};
149#[cfg(feature = "fs")]
150pub use fs::{resource_id_for_path, FileSystemBundler};
151pub use manifest::{Manifest, ResourceIdentifier};
152pub use pack::{pack, unpack};