diff --git a/Cargo.toml b/Cargo.toml index edbe40a..c8855a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,10 +16,13 @@ keywords = ["compression", "deflate", "macro", "include", "assets"] [dependencies] include-flate-codegen-exports = { version = "0.1.4", path = "codegen-exports" } lazy_static = "1.3" -libflate = "1.0.0" +libflate = { version = "2.0.0", default-features = false } +core2 = { version = "0.4", default-features = false, features = ["alloc"] } [badges] travis-ci = {repository = "SOF3/include-flate"} [features] +default = ["std"] stable = ["include-flate-codegen-exports/stable"] +std = ["include-flate-codegen-exports/std", "libflate/std", "core2/std"] \ No newline at end of file diff --git a/codegen-exports/Cargo.toml b/codegen-exports/Cargo.toml index 6afac48..4f19eb4 100644 --- a/codegen-exports/Cargo.toml +++ b/codegen-exports/Cargo.toml @@ -14,3 +14,4 @@ proc-macro-hack = "0.5.9" [features] stable = ["include-flate-codegen/stable"] +std = [] \ No newline at end of file diff --git a/codegen-exports/src/lib.rs b/codegen-exports/src/lib.rs index bbf4314..2d5eb40 100644 --- a/codegen-exports/src/lib.rs +++ b/codegen-exports/src/lib.rs @@ -1,5 +1,21 @@ +#![cfg_attr(not(any(test, feature = "std")), no_std)] + +extern crate alloc; + #[cfg_attr(feature = "stable", proc_macro_hack::proc_macro_hack)] pub use include_flate_codegen::deflate_file; #[cfg_attr(feature = "stable", proc_macro_hack::proc_macro_hack)] pub use include_flate_codegen::deflate_utf8_file; + +#[cfg(feature = "std")] +pub type String = ::std::string::String; + +#[cfg(not(feature = "std"))] +pub type String = ::alloc::string::String; + +#[cfg(feature = "std")] +pub type Vec = ::std::vec::Vec; + +#[cfg(not(feature = "std"))] +pub type Vec = ::alloc::vec::Vec; diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index d10a6e4..c9735b5 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -12,7 +12,7 @@ description = "Macro codegen for the include-flate crate" proc-macro = true [dependencies] -libflate = "1.0.0" +libflate = "2.0.0" proc-macro-hack = { version = "0.5.9", optional = true } proc-macro2 = "1.0.9" quote = "1.0.2" diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index d76a093..eb249d0 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -24,8 +24,8 @@ use std::str::from_utf8; use libflate::deflate::Encoder; use proc_macro::TokenStream; use proc_macro2::Span; -use quote::quote; -use syn::{Error, LitByteStr, LitStr, Result}; +use quote::{quote, ToTokens}; +use syn::{Error, ExprTuple, LitByteStr, LitStr, Result}; /// `deflate_file!("file")` is equivalent to `include_bytes!("file.gz")`. /// @@ -67,20 +67,42 @@ pub fn deflate_utf8_file(ts: TokenStream) -> TokenStream { } fn inner(ts: TokenStream, utf8: bool) -> Result> { + if let Ok(t) = syn::parse::(ts.clone()) { + if t.elems.len() != 2 { + panic!("expected a tuple of size 2 only"); + } + let (lit, base) = ( + t.elems.first().unwrap().into_token_stream(), + t.elems.last().unwrap().into_token_stream(), + ); + let (lit, base) = ( + syn::parse::(lit.into())?, + syn::parse::(base.into())?, + ); + let key = quote!(#base).to_string(); + compress_file_as_tokenstream(PathBuf::from(lit.value()), &key[1..key.len() - 1], utf8) + } else if let Ok(lit) = syn::parse::(ts) { + compress_file_as_tokenstream(PathBuf::from(lit.value()), "CARGO_MANIFEST_DIR", utf8) + } else { + panic!("invalid pattern") + } +} + +fn compress_file_as_tokenstream( + path: PathBuf, + key: &str, + utf8: bool, +) -> Result> { fn emap(error: E) -> Error { Error::new(Span::call_site(), error) } - let dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); - - let lit = syn::parse::(ts)?; - let path = PathBuf::from(lit.value()); - if path.is_absolute() { Err(emap("absolute paths are not supported"))?; } - let target = dir.join(path); + let dir = PathBuf::from(std::env::var(key).unwrap()); + let target: PathBuf = dir.join(path); let mut file = File::open(target).map_err(emap)?; diff --git a/src/lib.rs b/src/lib.rs index 9aa1b7c..7db1d2b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,10 @@ //! which might be undesirable if the data are too large. //! An actual installer is still required if the binary involves too many resources that do not need to be kept in RAM all time. +#![cfg_attr(not(any(test, feature = "std")), no_std)] + +extern crate alloc; + use libflate::deflate; /// The low-level macros used by this crate. @@ -92,6 +96,16 @@ pub use lazy_static::lazy_static; /// [6]: https://github.com/SOF3/include-flate/tree/master/tests #[macro_export] macro_rules! flate { + ($(#[$meta:meta])* + $(pub $(($($vis:tt)+))?)? static $name:ident: [u8] from $path:literal on $base:literal) => { + // HACK: workaround to make cargo auto rebuild on modification of source file + const _: &'static [u8] = include_bytes!(concat!(env!($base), "/", $path)); + $crate::lazy_static! { + $(#[$meta])* + $(pub $(($($vis)+))?)? static ref $name: $crate::codegen::Vec = $crate::decode($crate::codegen::deflate_file!(($path, $base))); + } + }; + ($(#[$meta:meta])* $(pub $(($($vis:tt)+))?)? static $name:ident: [u8] from $path:literal) => { // HACK: workaround to make cargo auto rebuild on modification of source file @@ -99,7 +113,17 @@ macro_rules! flate { $crate::lazy_static! { $(#[$meta])* - $(pub $(($($vis)+))?)? static ref $name: ::std::vec::Vec = $crate::decode($crate::codegen::deflate_file!($path)); + $(pub $(($($vis)+))?)? static ref $name: $crate::codegen::Vec = $crate::decode($crate::codegen::deflate_file!($path)); + } + }; + ($(#[$meta:meta])* + $(pub $(($($vis:tt)+))?)? static $name:ident: str from $path:literal on $base:literal) => { + // HACK: workaround to make cargo auto rebuild on modification of source file + const _: &'static str = include_str!(concat!(env!($base), "/", $path)); + + $crate::lazy_static! { + $(#[$meta])* + $(pub $(($($vis)+))?)? static ref $name: $crate::codegen::String = $crate::decode_string($crate::codegen::deflate_utf8_file!(($path, $base))); } }; ($(#[$meta:meta])* @@ -109,25 +133,25 @@ macro_rules! flate { $crate::lazy_static! { $(#[$meta])* - $(pub $(($($vis)+))?)? static ref $name: ::std::string::String = $crate::decode_string($crate::codegen::deflate_utf8_file!($path)); + $(pub $(($($vis)+))?)? static ref $name: $crate::codegen::String = $crate::decode_string($crate::codegen::deflate_utf8_file!($path)); } }; } #[doc(hidden)] -pub fn decode(bytes: &[u8]) -> Vec { - use std::io::{Cursor, Read}; +pub fn decode(bytes: &[u8]) -> codegen::Vec { + use core2::io::{Cursor, Read}; let mut dec = deflate::Decoder::new(Cursor::new(bytes)); - let mut ret = Vec::new(); + let mut ret = codegen::Vec::new(); dec.read_to_end(&mut ret) .expect("Compiled DEFLATE buffer was corrupted"); ret } #[doc(hidden)] -pub fn decode_string(bytes: &[u8]) -> String { +pub fn decode_string(bytes: &[u8]) -> codegen::String { // We should have checked for utf8 correctness in encode_utf8_file! - String::from_utf8(decode(bytes)) + codegen::String::from_utf8(decode(bytes)) .expect("flate_str has malformed UTF-8 despite checked at compile time") }