~repos /rust-embed

#rust#proc-macro#http

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.


fd159578 Tangent 128

6 years ago
Optimization: don't box iterators in release mode
Files changed (2) hide show
  1. impl/src/lib.rs +10 -6
  2. src/lib.rs +29 -0
impl/src/lib.rs CHANGED
@@ -48,8 +48,9 @@ fn generate_assets(ident: &syn::Ident, folder_path: String) -> quote::Tokens {
48
48
  fn get(&self, file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
49
49
  #ident::get(file_path)
50
50
  }
51
- fn iter(&self) -> Box<dyn Iterator<Item = std::borrow::Cow<'static, str>>> {
51
+ fn iter(&self) -> rust_embed::Filenames {
52
+ // the return type of iter() is unnamable, so we have to box it
52
- Box::new(#ident::iter())
53
+ rust_embed::Filenames::Dynamic(Box::new(#ident::iter()))
53
54
  }
54
55
  }
55
56
  }
@@ -83,17 +84,20 @@ fn generate_assets(ident: &syn::Ident, folder_path: String) -> quote::Tokens {
83
84
  }
84
85
  }
85
86
 
87
+ fn names() -> std::slice::Iter<'static, &'static str> {
88
+ const items: [&str; #array_len] = [#(#list_values),*];
89
+ items.iter()
90
+ }
86
91
  pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
87
- static items: [&str; #array_len] = [#(#list_values),*];
88
- items.iter().map(|x| std::borrow::Cow::from(*x))
92
+ Self::names().map(|x| std::borrow::Cow::from(*x))
89
93
  }
90
94
  }
91
95
  impl rust_embed::RustEmbed for #ident {
92
96
  fn get(&self, file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
93
97
  #ident::get(file_path)
94
98
  }
95
- fn iter(&self) -> Box<dyn Iterator<Item = std::borrow::Cow<'static, str>>> {
99
+ fn iter(&self) -> rust_embed::Filenames {
96
- Box::new(#ident::iter())
100
+ rust_embed::Filenames::Embedded(#ident::names())
97
101
  }
98
102
  }
99
103
  }
src/lib.rs CHANGED
@@ -44,3 +44,32 @@ pub trait RustEmbed {
44
44
  /// Otherwise, the files are listed from the file system on each call.
45
45
  fn iter(&self) -> Filenames;
46
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
+ }