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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Dir {
|
pub struct Dir {
|
||||||
/// The entries the directory houses.
|
/// The entries the directory houses.
|
||||||
pub children: Cow<'static, [DirEntry]>,
|
pub __children: Cow<'static, [DirEntry]>,
|
||||||
/// The absolute path of the directory.
|
/// 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 {
|
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.
|
/// Collects all files from the directory into a vector.
|
||||||
pub fn flatten(self) -> Vec<File> {
|
pub fn flatten(self) -> Vec<File> {
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
for child in self.children.into_owned() {
|
for child in self.__children.into_owned() {
|
||||||
// TODO: Eliminate allocation.
|
// TODO: Eliminate allocation.
|
||||||
match child {
|
match child {
|
||||||
DirEntry::File(file) => entries.push(file),
|
DirEntry::File(file) => entries.push(file),
|
||||||
|
@ -112,9 +123,21 @@ impl Dir {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
/// The content of the file in bytes.
|
/// The content of the file in bytes.
|
||||||
pub content: Cow<'static, [u8]>,
|
pub __content: Cow<'static, [u8]>,
|
||||||
/// The absolute path of the file.
|
/// 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> {
|
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 filetype = entry.file_type().expect("Failed to read entry filetype");
|
||||||
|
|
||||||
let path = Cow::Owned::<'static, Path>(
|
let path = entry
|
||||||
entry
|
.path()
|
||||||
.path()
|
.canonicalize()
|
||||||
.canonicalize()
|
.expect("Failed to canonicalize path");
|
||||||
.expect("Failed to canonicalize path"),
|
|
||||||
);
|
let path_str = path
|
||||||
|
.to_str()
|
||||||
|
.expect("Failed to convert OsStr to str")
|
||||||
|
.to_string();
|
||||||
|
|
||||||
if filetype.is_dir() {
|
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() {
|
} 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()
|
.canonicalize()
|
||||||
.expect("Failed to canonicalize path");
|
.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);
|
let children = read_dir(&directory);
|
||||||
|
|
||||||
Dir {
|
Dir {
|
||||||
children: children.into(),
|
__children: children.into(),
|
||||||
path: directory.into(),
|
__path: directory_str.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
path::PathBuf,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
use proc_macro as pm1;
|
use proc_macro as pm1;
|
||||||
|
@ -15,21 +15,6 @@ use syn::{
|
||||||
LitStr,
|
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>);
|
struct TokenVec(Vec<TokenStream>);
|
||||||
|
|
||||||
impl ToTokens for TokenVec {
|
impl ToTokens for TokenVec {
|
||||||
|
@ -37,8 +22,7 @@ impl ToTokens for TokenVec {
|
||||||
let inner = &self.0;
|
let inner = &self.0;
|
||||||
|
|
||||||
tokens.extend(quote! {{
|
tokens.extend(quote! {{
|
||||||
const CHILDREN: &[::embed::DirEntry] = &[#(#inner),*]; // FIXME: Not const.
|
::std::borrow::Cow::Borrowed(&[#(#inner),*])
|
||||||
::std::borrow::Cow::Borrowed(CHILDREN)
|
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 base = neighbor.parent().expect("Failed to get the parent of file");
|
||||||
|
|
||||||
let directory = PathBuf2(
|
let directory = base
|
||||||
base.join(path)
|
.join(path)
|
||||||
.canonicalize()
|
.canonicalize()
|
||||||
.expect("Failed to canonicalize path"),
|
.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! {
|
quote! {
|
||||||
::embed::Dir {
|
::embed::Dir {
|
||||||
children: #children,
|
__children: #children,
|
||||||
path: #directory,
|
__path: ::std::borrow::Cow::Borrowed(#directory_str),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_dir(directory: &PathBuf) -> TokenVec {
|
fn read_dir(directory: &Path) -> TokenVec {
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
for entry in fs::read_dir(directory).expect("Failed to list directory contents") {
|
for entry in fs::read_dir(directory).expect("Failed to list directory contents") {
|
||||||
let entry = entry.expect("Failed to read entry");
|
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")
|
.expect("Failed to get file metadata")
|
||||||
.file_type();
|
.file_type();
|
||||||
|
|
||||||
if filetype.is_dir() {
|
if filetype.is_dir() {
|
||||||
let children = read_dir(&path.0);
|
let children = read_dir(&path);
|
||||||
|
|
||||||
entries.push(quote! {
|
entries.push(quote! {
|
||||||
::embed::DirEntry::Dir(::embed::Dir {
|
::embed::DirEntry::Dir(::embed::Dir {
|
||||||
children: #children,
|
__children: #children,
|
||||||
path: #path,
|
__path: ::std::borrow::Cow::Borrowed(#path_str),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
} else if filetype.is_file() {
|
} else if filetype.is_file() {
|
||||||
let path_str = path
|
|
||||||
.0
|
|
||||||
.to_str()
|
|
||||||
.expect("Failed to get the string representation of PathBuf");
|
|
||||||
|
|
||||||
entries.push(quote! {
|
entries.push(quote! {
|
||||||
::embed::DirEntry::File(::embed::File {
|
::embed::DirEntry::File(::embed::File {
|
||||||
content: ::std::borrow::Cow::Borrowed(include_bytes!(#path_str)),
|
__content: ::std::borrow::Cow::Borrowed(include_bytes!(#path_str)),
|
||||||
path: #path,
|
__path: ::std::borrow::Cow::Borrowed(#path_str),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue