~repos /rust-embed
git clone https://pyrossh.dev/repos/rust-embed.git
rust macro which loads files into the rust binary at compile time during release and loads the file from the fs during dev.
b51c27da
—
Mark Drobnak 6 years ago
Merge pull request #49 from Tangent128/master
- impl/src/lib.rs +22 -2
- readme.md +8 -0
- src/lib.rs +64 -0
- tests/lib.rs +14 -0
impl/src/lib.rs
CHANGED
|
@@ -44,6 +44,15 @@ fn generate_assets(ident: &syn::Ident, folder_path: String) -> quote::Tokens {
|
|
|
44
44
|
get_files(String::from(#folder_path)).map(|e| std::borrow::Cow::from(e.rel_path))
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
impl rust_embed::RustEmbed for #ident {
|
|
48
|
+
fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
|
|
49
|
+
#ident::get(file_path)
|
|
50
|
+
}
|
|
51
|
+
fn iter() -> rust_embed::Filenames {
|
|
52
|
+
// the return type of iter() is unnamable, so we have to box it
|
|
53
|
+
rust_embed::Filenames::Dynamic(Box::new(#ident::iter()))
|
|
54
|
+
}
|
|
55
|
+
}
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
58
|
|
|
@@ -75,11 +84,22 @@ fn generate_assets(ident: &syn::Ident, folder_path: String) -> quote::Tokens {
|
|
|
75
84
|
}
|
|
76
85
|
}
|
|
77
86
|
|
|
87
|
+
fn names() -> std::slice::Iter<'static, &'static str> {
|
|
88
|
+
const items: [&str; #array_len] = [#(#list_values),*];
|
|
89
|
+
items.iter()
|
|
90
|
+
}
|
|
78
91
|
pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
|
|
79
|
-
static items: [&str; #array_len] = [#(#list_values),*];
|
|
80
|
-
|
|
92
|
+
Self::names().map(|x| std::borrow::Cow::from(*x))
|
|
81
93
|
}
|
|
82
94
|
}
|
|
95
|
+
impl rust_embed::RustEmbed for #ident {
|
|
96
|
+
fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
|
|
97
|
+
#ident::get(file_path)
|
|
98
|
+
}
|
|
99
|
+
fn iter() -> rust_embed::Filenames {
|
|
100
|
+
rust_embed::Filenames::Embedded(#ident::names())
|
|
101
|
+
}
|
|
102
|
+
}
|
|
83
103
|
}
|
|
84
104
|
}
|
|
85
105
|
|
readme.md
CHANGED
|
@@ -44,6 +44,14 @@ impl Asset {
|
|
|
44
44
|
...
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
impl RustEmbed for Asset {
|
|
48
|
+
fn get(file_path: &str) -> Option<Cow<'static, [u8]>> {
|
|
49
|
+
...
|
|
50
|
+
}
|
|
51
|
+
fn iter() -> impl Iterator<Item = Cow<'static, str>> {
|
|
52
|
+
...
|
|
53
|
+
}
|
|
54
|
+
}
|
|
47
55
|
```
|
|
48
56
|
|
|
49
57
|
### `get(file_path: &str)`
|
src/lib.rs
CHANGED
|
@@ -9,3 +9,67 @@ pub use rust_embed_impl::*;
|
|
|
9
9
|
#[doc(hidden)]
|
|
10
10
|
#[cfg(all(debug_assertions, not(feature = "debug-embed")))]
|
|
11
11
|
pub mod utils;
|
|
12
|
+
|
|
13
|
+
/// A directory of binary assets.
|
|
14
|
+
///
|
|
15
|
+
/// They should be embedded into the executable for release builds,
|
|
16
|
+
/// but can be read from the filesystem for debug builds.
|
|
17
|
+
///
|
|
18
|
+
/// This trait is meant to be derived like so:
|
|
19
|
+
/// ```
|
|
20
|
+
/// #[macro_use]
|
|
21
|
+
/// extern crate rust_embed;
|
|
22
|
+
/// #[derive(RustEmbed)]
|
|
23
|
+
/// #[folder = "examples/public/"]
|
|
24
|
+
/// struct Asset;
|
|
25
|
+
/// ```
|
|
26
|
+
|
|
27
|
+
pub trait RustEmbed {
|
|
28
|
+
/// Given a relative path from the assets folder, returns the bytes if found.
|
|
29
|
+
///
|
|
30
|
+
/// If the feature `debug-embed` is enabled or the binary is compiled in
|
|
31
|
+
/// release mode, the bytes have been embeded in the binary and a
|
|
32
|
+
/// `Cow::Borrowed(&'static [u8])` is returned.
|
|
33
|
+
///
|
|
34
|
+
/// Otherwise, the bytes are read from the file system on each call and a
|
|
35
|
+
/// `Cow::Owned(Vec<u8>)` is returned.
|
|
36
|
+
fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>>;
|
|
37
|
+
|
|
38
|
+
/// Iterates the files in this assets folder.
|
|
39
|
+
///
|
|
40
|
+
/// If the feature `debug-embed` is enabled or the binary is compiled in
|
|
41
|
+
/// release mode, a static array to the list of relative paths to the files
|
|
42
|
+
/// is used.
|
|
43
|
+
///
|
|
44
|
+
/// Otherwise, the files are listed from the file system on each call.
|
|
45
|
+
fn iter() -> Filenames;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// An iterator type over filenames.
|
|
49
|
+
///
|
|
50
|
+
/// This enum exists for optimization purposes, to avoid boxing the iterator in
|
|
51
|
+
/// some cases. Do not try and match on it, as different variants will exist
|
|
52
|
+
/// depending on the compilation context.
|
|
53
|
+
pub enum Filenames {
|
|
54
|
+
/// Release builds use a nameable iterator type, which can be stack-allocated.
|
|
55
|
+
#[cfg(any(not(debug_assertions), feature = "debug-embed"))]
|
|
56
|
+
Embedded(std::slice::Iter<'static, &'static str>),
|
|
57
|
+
|
|
58
|
+
/// The debug iterator type is currently unnamable and still needs to be
|
|
59
|
+
/// boxed.
|
|
60
|
+
#[cfg(all(debug_assertions, not(feature = "debug-embed")))]
|
|
61
|
+
Dynamic(Box<dyn Iterator<Item = std::borrow::Cow<'static, str>>>),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
impl Iterator for Filenames {
|
|
65
|
+
type Item = std::borrow::Cow<'static, str>;
|
|
66
|
+
fn next(&mut self) -> Option<Self::Item> {
|
|
67
|
+
match self {
|
|
68
|
+
#[cfg(any(not(debug_assertions), feature = "debug-embed"))]
|
|
69
|
+
Filenames::Embedded(names) => names.next().map(|x| std::borrow::Cow::from(*x)),
|
|
70
|
+
|
|
71
|
+
#[cfg(all(debug_assertions, not(feature = "debug-embed")))]
|
|
72
|
+
Filenames::Dynamic(boxed) => boxed.next(),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
tests/lib.rs
CHANGED
|
@@ -31,3 +31,17 @@ fn iter_works() {
|
|
|
31
31
|
}
|
|
32
32
|
assert_eq!(num_files, 6);
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
#[test]
|
|
36
|
+
fn trait_works_generic() {
|
|
37
|
+
trait_works_generic_helper::<Asset>();
|
|
38
|
+
}
|
|
39
|
+
fn trait_works_generic_helper<E: rust_embed::RustEmbed>() {
|
|
40
|
+
let mut num_files = 0;
|
|
41
|
+
for file in E::iter() {
|
|
42
|
+
assert!(E::get(file.as_ref()).is_some());
|
|
43
|
+
num_files += 1;
|
|
44
|
+
}
|
|
45
|
+
assert_eq!(num_files, 6);
|
|
46
|
+
assert!(E::get("gg.html").is_none(), "gg.html should not exist");
|
|
47
|
+
}
|