From 23886aa7781db6c78df5a31347dff94678000772 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 4 Jan 2024 16:41:05 +0300 Subject: [PATCH] Combine embed/ into lib.rs and document code --- embed/src/dir.rs | 75 -------------------- embed/src/file.rs | 61 ---------------- embed/src/lib.rs | 177 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 173 insertions(+), 140 deletions(-) delete mode 100644 embed/src/dir.rs delete mode 100644 embed/src/file.rs diff --git a/embed/src/dir.rs b/embed/src/dir.rs deleted file mode 100644 index 406d67e..0000000 --- a/embed/src/dir.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::{ - fs::{ - self, - }, - path::PathBuf, -}; - -#[derive(Debug, Clone)] -pub enum DirEntry { - Dir(Dir), - File(File), -} - -#[derive(Debug, Clone)] -pub struct Dir { - pub children: Vec, - pub path: PathBuf, -} - -impl Dir { - pub fn flatten(self) -> Vec { - let mut entries = Vec::new(); - - for child in self.children { - match child { - DirEntry::File(file) => entries.push(file), - DirEntry::Dir(dir) => entries.append(&mut dir.flatten()), - } - } - - entries - } -} - -#[derive(Debug, Clone)] -pub struct File { - pub content: Vec, - pub path: PathBuf, -} - -fn read_dir(path: &PathBuf) -> Vec { - dbg!(path); - let mut entries = Vec::new(); - - for entry in fs::read_dir(path).expect("Failed to list directory contents") { - let entry = entry.expect("Failed to read entry"); - - let filetype = entry.file_type().expect("Failed to read entry filetype"); - let path = entry.path(); - - if filetype.is_dir() { - let children = read_dir(&path); - - entries.push(DirEntry::Dir(Dir { children, path })) - } else if filetype.is_file() { - let content = fs::read(&path).expect("Failed to read file contents"); - - entries.push(DirEntry::File(File { content, path })) - } - } - - entries -} - -#[doc(hidden)] -pub fn __include_dir_runtime(caller: &str, path: &str) -> Dir { - let path = PathBuf::from(caller) - .parent() - .expect("Failed to get the parent of file") - .join(path); - - let children = read_dir(&path); - - Dir { children, path } -} diff --git a/embed/src/file.rs b/embed/src/file.rs deleted file mode 100644 index 26ef96e..0000000 --- a/embed/src/file.rs +++ /dev/null @@ -1,61 +0,0 @@ -#[macro_export] -macro_rules! string { - ($path:literal) => {{ - use ::std::borrow::Cow; - - #[cfg(debug_assertions)] - { - use ::std::{ - fs, - path::Path, - }; - - let file = Path::new(file!()) - .parent() - .expect("embed: Failed to get the parent of file") - .join($path); - - Cow::<'static, str>::Owned(fs::read_to_string(&file).unwrap_or_else(|error| { - panic!( - "embed: Failed to read file {file}: {error}", - file = file.display() - ) - })) - } - #[cfg(not(debug_assertions))] - { - Cow::Borrowed(include_str!($path)) - } - }}; -} - -#[macro_export] -macro_rules! bytes { - ($path:literal) => {{ - use ::std::borrow::Cow; - - #[cfg(debug_assertions)] - { - use ::std::{ - fs, - path::Path, - }; - - let file = Path::new(file!()) - .parent() - .expect("embed: Failed to get the parent of file") - .join($path); - - Cow::<'static, [u8]>::Owned(fs::read(&file).unwrap_or_else(|error| { - panic!( - "embed: failed to read file {file}: {error}", - file = file.display() - ) - })) - } - #[cfg(not(debug_assertions))] - { - Cow::Borrowed(include_bytes!($path)) - } - }}; -} diff --git a/embed/src/lib.rs b/embed/src/lib.rs index 24a9aba..abe5957 100644 --- a/embed/src/lib.rs +++ b/embed/src/lib.rs @@ -1,7 +1,176 @@ #![cfg(procmacro2_semver_exempt)] -mod dir; -mod file; +use std::{ + fs, + path::{ + Path, + PathBuf, + }, +}; -pub use dir::*; -pub use embed_macros::dir; +#[doc(hidden)] +pub fn __string_runtime(neighbor: &str, path: &str) -> String { + let base = Path::new(neighbor) + .parent() + .expect("Failed to get the parent of file"); + + let file = base.join(path); + + fs::read_to_string(file).expect("Failed to read file") +} + +#[doc(hidden)] +pub fn __bytes_runtime(neighbor: &str, path: &str) -> Vec { + let base = Path::new(neighbor) + .parent() + .expect("Failed to get the parent of file"); + + let file = base.join(path); + + fs::read(file).expect("Failed to read file") +} + +/// Embed a files contents as a &str on release, +/// read from the filesystem as a String on debug. +/// +/// # Example +/// +/// ``` +/// fn main() { +/// let content = embed::string!("main.rs"); +/// } +/// ``` +#[macro_export] +macro_rules! string { + ($path:literal) => {{ + use ::std::borrow::Cow; + + #[cfg(debug_assertions)] + { + Cow::Owned(::embed::__string_runtime(file!(), $path)) + } + #[cfg(not(debug_assertions))] + { + Cow::Borrowed(include_str!($path)) + } + }}; +} + +/// Embed a files contents as a &[u8] on release, +/// read from the filesystem as a Vec on debug. +/// +/// # Example +/// +/// ``` +/// fn main() { +/// // `assets/` is in the same directory as `src/` +/// let content = embed::string!("../assets/icon.png"); +/// } +/// ``` +#[macro_export] +macro_rules! bytes { + ($path:literal) => {{ + #[cfg(debug_assertions)] + { + ::std::borrow::Cow::Owned(::embed::__bytes_runtime(file!(), $path)) + } + #[cfg(not(debug_assertions))] + { + ::std::borrow::Cow::Borrowed(include_bytes!($path)) + } + }}; +} + +/// A directory entry. +#[derive(Debug, Clone)] +pub enum DirEntry { + /// A directory. + Dir(Dir), + /// A file. + File(File), +} + +/// A directory. +#[derive(Debug, Clone)] +pub struct Dir { + /// The entries the directory houses. + pub children: Vec, + /// The absolute path of the directory. + pub path: PathBuf, +} + +impl Dir { + /// Collects all files from the directory into a vector. + pub fn flatten(self) -> Vec { + let mut entries = Vec::new(); + + for child in self.children { + match child { + DirEntry::File(file) => entries.push(file), + DirEntry::Dir(dir) => entries.append(&mut dir.flatten()), + } + } + + entries + } +} + +/// A file. +#[derive(Debug, Clone)] +pub struct File { + /// The content of the file in bytes. + pub content: Vec, + /// The absolute path of the file. + pub path: PathBuf, +} + +impl File { + /// Returns the content of the file as a String if it is valid UTF-8. + pub fn content_string(&self) -> Option { + String::from_utf8(&self.content).ok() + } +} + +fn read_dir(path: &PathBuf) -> Vec { + let mut entries = Vec::new(); + + for entry in fs::read_dir(path).expect("Failed to list directory contents") { + let entry = entry.expect("Failed to read entry"); + + let filetype = entry.file_type().expect("Failed to read entry filetype"); + + let path = entry + .path() + .canonicalize() + .expect("Failed to canonicalize path"); + + if filetype.is_dir() { + let children = read_dir(&path); + + entries.push(DirEntry::Dir(Dir { children, path })) + } else if filetype.is_file() { + let content = fs::read(&path).expect("Failed to read file contents"); + + entries.push(DirEntry::File(File { content, path })) + } + } + + entries +} + +#[doc(hidden)] +pub fn __dir_runtime(neighbor: &str, path: &str) -> Dir { + let base = Path::new(neighbor) + .parent() + .expect("Failed to get the parent of file"); + + let directory = base + .join(path) + .canonicalize() + .expect("Failed to canonicalize path"); + + Dir { + children: read_dir(&directory), + path: directory, + } +}