Skip to content

Commit

Permalink
Merge pull request #217 from osiewicz/binary_search_by_path
Browse files Browse the repository at this point in the history
feat: Store file contents statically and use binary search for lookup.
  • Loading branch information
Peter John committed Aug 23, 2023
2 parents 1623d29 + 01a4457 commit c286171
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 19 deletions.
54 changes: 37 additions & 17 deletions impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use std::{
collections::BTreeMap,
env,
iter::FromIterator,
path::{Path, PathBuf},
Expand All @@ -18,13 +19,13 @@ fn embedded(
) -> TokenStream2 {
extern crate rust_embed_utils;

let mut match_values = Vec::<TokenStream2>::new();
let mut match_values = BTreeMap::new();
let mut list_values = Vec::<String>::new();

let includes: Vec<&str> = includes.iter().map(AsRef::as_ref).collect();
let excludes: Vec<&str> = excludes.iter().map(AsRef::as_ref).collect();
for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(absolute_folder_path.clone(), &includes, &excludes) {
match_values.push(embed_file(relative_folder_path.clone(), &rel_path, &full_canonical_path));
match_values.insert(rel_path.clone(), embed_file(relative_folder_path.clone(), &rel_path, &full_canonical_path));

list_values.push(if let Some(prefix) = prefix {
format!("{}{}", prefix, rel_path)
Expand All @@ -50,17 +51,33 @@ fn embedded(
} else {
TokenStream2::new()
};

let match_values = match_values.into_iter().map(|(path, bytes)| {
quote! {
(#path, #bytes),
}
});
let value_type = if cfg!(feature = "compression") {
quote! { fn() -> rust_embed::EmbeddedFile }
} else {
quote! { rust_embed::EmbeddedFile }
};
let get_value = if cfg!(feature = "compression") {
quote! {|idx| (ENTRIES[idx].1)()}
} else {
quote! {|idx| ENTRIES[idx].1.clone()}
};
quote! {
#not_debug_attr
impl #ident {
/// Get an embedded file and its metadata.
pub fn get(file_path: &str) -> Option<rust_embed::EmbeddedFile> {
#handle_prefix
match file_path.replace("\\", "/").as_str() {
#(#match_values)*
_ => None,
}
let key = file_path.replace("\\", "/");
const ENTRIES: &'static [(&'static str, #value_type)] = &[
#(#match_values)*];
let position = ENTRIES.binary_search_by_key(&key.as_str(), |entry| entry.0);
position.ok().map(#get_value)

}

fn names() -> std::slice::Iter<'static, &'static str> {
Expand Down Expand Up @@ -202,23 +219,26 @@ fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &s
let full_relative_path = PathBuf::from_iter([folder_path.expect("folder_path must be provided under `compression` feature"), rel_path]);
let full_relative_path = full_relative_path.to_string_lossy();
quote! {
rust_embed::flate!(static FILE: [u8] from #full_relative_path);
let bytes = &FILE[..];
rust_embed::flate!(static BYTES: [u8] from #full_relative_path);
}
} else {
quote! {
let bytes = &include_bytes!(#full_canonical_path)[..];
const BYTES: &'static [u8] = include_bytes!(#full_canonical_path);
}
};

let closure_args = if cfg!(feature = "compression") {
quote! { || }
} else {
quote! {}
};
quote! {
#rel_path => {
#embedding_code
#closure_args {
#embedding_code

Some(rust_embed::EmbeddedFile {
data: std::borrow::Cow::from(bytes),
metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
})
rust_embed::EmbeddedFile {
data: std::borrow::Cow::Borrowed(&BYTES),
metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@ pub fn get_files<'patterns>(folder_path: String, includes: &'patterns [&str], ex
}

/// A file embedded into the binary
#[derive(Clone)]
pub struct EmbeddedFile {
pub data: Cow<'static, [u8]>,
pub metadata: Metadata,
}

/// Metadata about an embedded file
#[derive(Clone)]
pub struct Metadata {
hash: [u8; 32],
last_modified: Option<u64>,
Expand All @@ -93,12 +95,12 @@ pub struct Metadata {

impl Metadata {
#[doc(hidden)]
pub fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>, #[cfg(feature = "mime-guess")] mimetype: &'static str) -> Self {
pub const fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>, #[cfg(feature = "mime-guess")] mimetype: &'static str) -> Self {
Self {
hash,
last_modified,
#[cfg(feature = "mime-guess")]
mimetype: mimetype.into(),
mimetype: Cow::Borrowed(mimetype),
}
}

Expand Down

0 comments on commit c286171

Please sign in to comment.