mirror of
https://github.com/RGBCube/embd-rs
synced 2025-07-27 05:27:44 +00:00
Don't allocate for the children on release
This commit is contained in:
parent
2f2ec0f0c4
commit
161beeaf57
2 changed files with 77 additions and 56 deletions
|
@ -86,17 +86,28 @@ pub enum DirEntry {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Dir {
|
||||
/// The entries the directory houses.
|
||||
pub children: Cow<'static, [DirEntry]>,
|
||||
pub __children: Cow<'static, [DirEntry]>,
|
||||
/// The absolute path of the directory.
|
||||
pub path: Cow<'static, Path>,
|
||||
pub __path: Cow<'static, str>, /* We are making it a &str because *
|
||||
* include_*! takes a string anyway. */
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
/// Returns the children of the directory.
|
||||
pub fn children(&self) -> &[DirEntry] {
|
||||
&self.__children
|
||||
}
|
||||
|
||||
/// Returns the path of the directory.
|
||||
pub fn path(&self) -> &Path {
|
||||
Path::new(self.__path.as_ref().into())
|
||||
}
|
||||
|
||||
/// Collects all files from the directory into a vector.
|
||||
pub fn flatten(self) -> Vec<File> {
|
||||
let mut entries = Vec::new();
|
||||
|
||||
for child in self.children.into_owned() {
|
||||
for child in self.__children.into_owned() {
|
||||
// TODO: Eliminate allocation.
|
||||
match child {
|
||||
DirEntry::File(file) => entries.push(file),
|
||||
|
@ -112,9 +123,21 @@ impl Dir {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct File {
|
||||
/// The content of the file in bytes.
|
||||
pub content: Cow<'static, [u8]>,
|
||||
pub __content: Cow<'static, [u8]>,
|
||||
/// The absolute path of the file.
|
||||
pub path: Cow<'static, Path>,
|
||||
pub __path: Cow<'static, str>,
|
||||
}
|
||||
|
||||
impl File {
|
||||
/// Returns the content of the file.
|
||||
pub fn content(&self) -> &[u8] {
|
||||
&self.__content
|
||||
}
|
||||
|
||||
/// Returns the path of the file.
|
||||
pub fn path(&self) -> &Path {
|
||||
Path::new(self.__path.as_ref().into())
|
||||
}
|
||||
}
|
||||
|
||||
fn read_dir(directory: &Path) -> Vec<DirEntry> {
|
||||
|
@ -125,21 +148,30 @@ fn read_dir(directory: &Path) -> Vec<DirEntry> {
|
|||
|
||||
let filetype = entry.file_type().expect("Failed to read entry filetype");
|
||||
|
||||
let path = Cow::Owned::<'static, Path>(
|
||||
entry
|
||||
.path()
|
||||
.canonicalize()
|
||||
.expect("Failed to canonicalize path"),
|
||||
);
|
||||
let path = entry
|
||||
.path()
|
||||
.canonicalize()
|
||||
.expect("Failed to canonicalize path");
|
||||
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.expect("Failed to convert OsStr to str")
|
||||
.to_string();
|
||||
|
||||
if filetype.is_dir() {
|
||||
let children = Cow::Owned(read_dir(path.as_ref()));
|
||||
let children = read_dir(&path);
|
||||
|
||||
entries.push(DirEntry::Dir(Dir { children, path }))
|
||||
entries.push(DirEntry::Dir(Dir {
|
||||
__children: children.into(),
|
||||
__path: path_str.into(),
|
||||
}))
|
||||
} else if filetype.is_file() {
|
||||
let content = Cow::Owned(fs::read(&path).expect("Failed to read file contents"));
|
||||
let content = fs::read(&path).expect("Failed to read file contents");
|
||||
|
||||
entries.push(DirEntry::File(File { content, path }))
|
||||
entries.push(DirEntry::File(File {
|
||||
__content: content.into(),
|
||||
__path: path_str.into(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,11 +187,16 @@ pub fn __dir_runtime(neighbor: &str, path: &str) -> Dir {
|
|||
.canonicalize()
|
||||
.expect("Failed to canonicalize path");
|
||||
|
||||
let directory_str = directory
|
||||
.to_str()
|
||||
.expect("Failed to convert OsStr to str")
|
||||
.to_string();
|
||||
|
||||
let children = read_dir(&directory);
|
||||
|
||||
Dir {
|
||||
children: children.into(),
|
||||
path: directory.into(),
|
||||
__children: children.into(),
|
||||
__path: directory_str.into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{
|
||||
fs,
|
||||
path::PathBuf,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use proc_macro as pm1;
|
||||
|
@ -15,21 +15,6 @@ use syn::{
|
|||
LitStr,
|
||||
};
|
||||
|
||||
struct PathBuf2(PathBuf);
|
||||
|
||||
impl ToTokens for PathBuf2 {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let raw = self
|
||||
.0
|
||||
.to_str()
|
||||
.expect("Failed to get the string representation of PathBuf");
|
||||
|
||||
tokens.extend(quote! {
|
||||
::std::borrow::Cow::Borrowed(::std::path::Path::new(#raw))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
struct TokenVec(Vec<TokenStream>);
|
||||
|
||||
impl ToTokens for TokenVec {
|
||||
|
@ -37,8 +22,7 @@ impl ToTokens for TokenVec {
|
|||
let inner = &self.0;
|
||||
|
||||
tokens.extend(quote! {{
|
||||
const CHILDREN: &[::embed::DirEntry] = &[#(#inner),*]; // FIXME: Not const.
|
||||
::std::borrow::Cow::Borrowed(CHILDREN)
|
||||
::std::borrow::Cow::Borrowed(&[#(#inner),*])
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
@ -77,53 +61,53 @@ fn dir_release(input: TokenStream, path: &str) -> TokenStream {
|
|||
|
||||
let base = neighbor.parent().expect("Failed to get the parent of file");
|
||||
|
||||
let directory = PathBuf2(
|
||||
base.join(path)
|
||||
.canonicalize()
|
||||
.expect("Failed to canonicalize path"),
|
||||
);
|
||||
let directory = base
|
||||
.join(path)
|
||||
.canonicalize()
|
||||
.expect("Failed to canonicalize path");
|
||||
|
||||
let children = read_dir(&directory.0);
|
||||
let directory_str = directory.to_str().expect("Failed to convert OsStr to str");
|
||||
|
||||
let children = read_dir(&directory);
|
||||
|
||||
quote! {
|
||||
::embed::Dir {
|
||||
children: #children,
|
||||
path: #directory,
|
||||
__children: #children,
|
||||
__path: ::std::borrow::Cow::Borrowed(#directory_str),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_dir(directory: &PathBuf) -> TokenVec {
|
||||
fn read_dir(directory: &Path) -> TokenVec {
|
||||
let mut entries = Vec::new();
|
||||
|
||||
for entry in fs::read_dir(directory).expect("Failed to list directory contents") {
|
||||
let entry = entry.expect("Failed to read entry");
|
||||
|
||||
let path = PathBuf2(entry.path());
|
||||
let path = entry.path();
|
||||
|
||||
let filetype = fs::metadata(&path.0)
|
||||
let path_str = path
|
||||
.to_str()
|
||||
.expect("Failed to get the string representation of PathBuf");
|
||||
|
||||
let filetype = fs::metadata(&path)
|
||||
.expect("Failed to get file metadata")
|
||||
.file_type();
|
||||
|
||||
if filetype.is_dir() {
|
||||
let children = read_dir(&path.0);
|
||||
let children = read_dir(&path);
|
||||
|
||||
entries.push(quote! {
|
||||
::embed::DirEntry::Dir(::embed::Dir {
|
||||
children: #children,
|
||||
path: #path,
|
||||
__children: #children,
|
||||
__path: ::std::borrow::Cow::Borrowed(#path_str),
|
||||
})
|
||||
});
|
||||
} else if filetype.is_file() {
|
||||
let path_str = path
|
||||
.0
|
||||
.to_str()
|
||||
.expect("Failed to get the string representation of PathBuf");
|
||||
|
||||
entries.push(quote! {
|
||||
::embed::DirEntry::File(::embed::File {
|
||||
content: ::std::borrow::Cow::Borrowed(include_bytes!(#path_str)),
|
||||
path: #path,
|
||||
__content: ::std::borrow::Cow::Borrowed(include_bytes!(#path_str)),
|
||||
__path: ::std::borrow::Cow::Borrowed(#path_str),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue