diff --git a/embed/src/lib.rs b/embed/src/lib.rs index 459aadc..e3ec254 100644 --- a/embed/src/lib.rs +++ b/embed/src/lib.rs @@ -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 { 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 { @@ -125,21 +148,30 @@ fn read_dir(directory: &Path) -> Vec { 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(), } } diff --git a/embed_macros/src/lib.rs b/embed_macros/src/lib.rs index d015ecc..5075bfa 100644 --- a/embed_macros/src/lib.rs +++ b/embed_macros/src/lib.rs @@ -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); 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), }) }); }