~repos /rust-embed
git clone https://pyrossh.dev/repos/rust-embed.git
rust macro which loads files into the rust binary at compile time during release and loads the file from the fs during dev.
d476f3e0
—
Peter John 5 years ago
Merge pull request #100 from paolobarbolini/improvements
- .travis.yml +0 -2
- Cargo.toml +11 -5
- examples/actix.rs +6 -9
- examples/basic.rs +1 -2
- examples/rocket.rs +4 -4
- examples/warp.rs +19 -19
- impl/Cargo.toml +2 -1
- impl/src/lib.rs +2 -7
- readme.md +5 -2
- src/lib.rs +2 -7
- tests/interpolated_path.rs +7 -11
- tests/lib.rs +7 -11
- utils/Cargo.toml +1 -0
- utils/src/lib.rs +0 -3
.travis.yml
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
language: rust
|
|
2
|
-
sudo: false
|
|
3
|
-
dist: trusty
|
|
4
2
|
rust:
|
|
5
3
|
- stable
|
|
6
4
|
- nightly
|
Cargo.toml
CHANGED
|
@@ -9,6 +9,7 @@ license = "MIT"
|
|
|
9
9
|
keywords = ["http", "rocket", "static", "web", "server"]
|
|
10
10
|
categories = ["web-programming::http-server"]
|
|
11
11
|
authors = ["pyros2097 <pyros2097@gmail.com>"]
|
|
12
|
+
edition = "2018"
|
|
12
13
|
|
|
13
14
|
[dependencies]
|
|
14
15
|
walkdir = "2.2.7"
|
|
@@ -16,18 +17,20 @@ rust-embed-impl = { version = "5.3.0", path = "impl"}
|
|
|
16
17
|
rust-embed-utils = { version = "5.0.0", path = "utils"}
|
|
17
18
|
|
|
18
19
|
include-flate = { version = "0.1", optional = true, features = ["stable"] }
|
|
20
|
+
actix-web = { version = "2", default-features = false, optional = true }
|
|
19
|
-
actix-
|
|
21
|
+
actix-rt = { version = "1", optional = true }
|
|
20
22
|
mime_guess = { version = "2", optional = true }
|
|
23
|
+
tokio = { version = "0.2", optional = true, features = ["macros"] }
|
|
21
|
-
warp = { version = "0.
|
|
24
|
+
warp = { version = "0.2", default-features = false, optional = true }
|
|
22
|
-
rocket = { version = "0.4.2", optional = true }
|
|
25
|
+
rocket = { version = "0.4.2", default-features = false, optional = true }
|
|
23
26
|
|
|
24
27
|
[features]
|
|
25
28
|
debug-embed = ["rust-embed-impl/debug-embed", "rust-embed-utils/debug-embed"]
|
|
26
29
|
interpolate-folder-path = ["rust-embed-impl/interpolate-folder-path"]
|
|
27
30
|
compression = ["rust-embed-impl/compression", "include-flate"]
|
|
28
31
|
nightly = ["rocket"]
|
|
29
|
-
actix = ["actix-web", "mime_guess"]
|
|
32
|
+
actix = ["actix-web", "actix-rt", "mime_guess"]
|
|
30
|
-
warp-ex = ["warp", "mime_guess"]
|
|
33
|
+
warp-ex = ["warp", "tokio", "mime_guess"]
|
|
31
34
|
|
|
32
35
|
[badges]
|
|
33
36
|
appveyor = { repository = "pyros2097/rust-embed" }
|
|
@@ -35,3 +38,6 @@ travis-ci = { repository = "pyros2097/rust-embed" }
|
|
|
35
38
|
is-it-maintained-issue-resolution = { repository = "pyros2097/rust-embed" }
|
|
36
39
|
is-it-maintained-open-issues = { repository = "pyros2097/rust-embed" }
|
|
37
40
|
maintenance = { status = "passively-maintained" }
|
|
41
|
+
|
|
42
|
+
[workspace]
|
|
43
|
+
members = ["impl", "utils"]
|
examples/actix.rs
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
extern crate actix_web;
|
|
2
|
-
#[macro_use]
|
|
3
|
-
extern crate rust_embed;
|
|
4
|
-
extern crate mime_guess;
|
|
5
|
-
|
|
6
1
|
use actix_web::body::Body;
|
|
7
2
|
use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer};
|
|
8
3
|
use mime_guess::from_path;
|
|
4
|
+
use rust_embed::RustEmbed;
|
|
5
|
+
|
|
9
6
|
use std::borrow::Cow;
|
|
10
7
|
|
|
11
8
|
#[derive(RustEmbed)]
|
|
@@ -34,14 +31,14 @@ fn dist(req: HttpRequest) -> HttpResponse {
|
|
|
34
31
|
handle_embedded_file(path)
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
#[actix_rt::main]
|
|
35
|
+
async fn main() -> std::io::Result<()> {
|
|
38
36
|
HttpServer::new(|| {
|
|
39
37
|
App::new()
|
|
40
38
|
.service(web::resource("/").route(web::get().to(index)))
|
|
41
39
|
.service(web::resource("/dist/{_:.*}").route(web::get().to(dist)))
|
|
42
40
|
})
|
|
43
|
-
.bind("127.0.0.1:8000")
|
|
41
|
+
.bind("127.0.0.1:8000")?
|
|
44
|
-
.unwrap()
|
|
45
42
|
.run()
|
|
46
|
-
.
|
|
43
|
+
.await
|
|
47
44
|
}
|
examples/basic.rs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
#[macro_use]
|
|
2
|
-
|
|
1
|
+
use rust_embed::RustEmbed;
|
|
3
2
|
|
|
4
3
|
#[derive(RustEmbed)]
|
|
5
4
|
#[folder = "examples/public/"]
|
examples/rocket.rs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#![feature(decl_macro, proc_macro_hygiene)]
|
|
2
2
|
#[macro_use]
|
|
3
3
|
extern crate rocket;
|
|
4
|
-
#[macro_use]
|
|
5
|
-
extern crate rust_embed;
|
|
6
4
|
|
|
7
5
|
use rocket::http::{ContentType, Status};
|
|
8
6
|
use rocket::response;
|
|
7
|
+
use rust_embed::RustEmbed;
|
|
8
|
+
|
|
9
9
|
use std::ffi::OsStr;
|
|
10
10
|
use std::io::Cursor;
|
|
11
11
|
use std::path::PathBuf;
|
|
@@ -32,8 +32,8 @@ fn dist<'r>(file: PathBuf) -> response::Result<'r> {
|
|
|
32
32
|
.as_path()
|
|
33
33
|
.extension()
|
|
34
34
|
.and_then(OsStr::to_str)
|
|
35
|
-
.
|
|
35
|
+
.ok_or_else(|| Status::new(400, "Could not get file extension"))?;
|
|
36
|
-
let content_type = ContentType::from_extension(ext).
|
|
36
|
+
let content_type = ContentType::from_extension(ext).ok_or_else(|| Status::new(400, "Could not get file content type"))?;
|
|
37
37
|
response::Response::build().header(content_type).sized_body(Cursor::new(d)).ok()
|
|
38
38
|
},
|
|
39
39
|
)
|
examples/warp.rs
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
#![deny(warnings)]
|
|
2
|
-
|
|
3
|
-
#[macro_use]
|
|
4
|
-
|
|
1
|
+
use rust_embed::RustEmbed;
|
|
5
|
-
extern crate warp;
|
|
6
|
-
|
|
7
|
-
use std::borrow::Cow;
|
|
8
|
-
use warp::{
|
|
2
|
+
use warp::{http::header::HeaderValue, path::Tail, reply::Response, Filter, Rejection, Reply};
|
|
9
3
|
|
|
10
4
|
#[derive(RustEmbed)]
|
|
11
5
|
#[folder = "examples/public/"]
|
|
12
6
|
struct Asset;
|
|
13
7
|
|
|
8
|
+
#[tokio::main]
|
|
14
|
-
fn main() {
|
|
9
|
+
async fn main() {
|
|
15
|
-
let
|
|
10
|
+
let index_html = warp::path::end().and_then(serve_index);
|
|
11
|
+
let dist = warp::path!("dist").and(warp::path::tail()).and_then(serve);
|
|
16
12
|
|
|
13
|
+
let routes = index_html.or(dist);
|
|
17
|
-
|
|
14
|
+
warp::serve(routes).run(([127, 0, 0, 1], 8080)).await;
|
|
15
|
+
}
|
|
18
16
|
|
|
17
|
+
async fn serve_index() -> Result<impl Reply, Rejection> {
|
|
19
|
-
|
|
18
|
+
serve_impl("index.html")
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
async fn serve(path: Tail) -> Result<impl Reply, Rejection> {
|
|
22
|
+
serve_impl(path.as_str())
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
fn
|
|
25
|
+
fn serve_impl(path: &str) -> Result<impl Reply, Rejection> {
|
|
26
|
+
let asset = Asset::get(path).ok_or_else(warp::reject::not_found)?;
|
|
25
27
|
let mime = mime_guess::from_path(path).first_or_octet_stream();
|
|
26
28
|
|
|
27
|
-
let asset: Option<Cow<'static, [u8]>> = Asset::get(path);
|
|
28
|
-
|
|
29
|
-
let
|
|
29
|
+
let mut res = Response::new(asset.into());
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
res.headers_mut().insert("content-type", HeaderValue::from_str(mime.as_ref()).unwrap());
|
|
31
|
+
Ok(res)
|
|
32
32
|
}
|
impl/Cargo.toml
CHANGED
|
@@ -9,6 +9,7 @@ license = "MIT"
|
|
|
9
9
|
keywords = ["http", "rocket", "static", "web", "server"]
|
|
10
10
|
categories = ["web-programming::http-server"]
|
|
11
11
|
authors = ["pyros2097 <pyros2097@gmail.com>"]
|
|
12
|
+
edition = "2018"
|
|
12
13
|
|
|
13
14
|
[lib]
|
|
14
15
|
proc-macro = true
|
|
@@ -21,7 +22,7 @@ quote = "1"
|
|
|
21
22
|
walkdir = "2.2.7"
|
|
22
23
|
|
|
23
24
|
[dependencies.shellexpand]
|
|
24
|
-
version = "
|
|
25
|
+
version = "2"
|
|
25
26
|
optional = true
|
|
26
27
|
|
|
27
28
|
[features]
|
impl/src/lib.rs
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
#![recursion_limit = "1024"]
|
|
2
|
-
extern crate proc_macro;
|
|
3
2
|
#[macro_use]
|
|
4
3
|
extern crate quote;
|
|
5
|
-
extern crate syn;
|
|
6
|
-
|
|
7
|
-
#[cfg(feature = "interpolate-folder-path")]
|
|
8
|
-
extern crate shellexpand;
|
|
9
|
-
extern crate
|
|
4
|
+
extern crate proc_macro;
|
|
10
5
|
|
|
11
6
|
use proc_macro::TokenStream;
|
|
12
7
|
use std::path::Path;
|
|
@@ -158,7 +153,7 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
|
|
|
158
153
|
|
|
159
154
|
// Add a message about the interpolate-folder-path feature if the path may
|
|
160
155
|
// include a variable
|
|
161
|
-
if folder_path.contains(
|
|
156
|
+
if folder_path.contains('$') && cfg!(not(feature = "interpolate-folder-path")) {
|
|
162
157
|
message += "\nA variable has been detected. RustEmbed can expand variables \
|
|
163
158
|
when the `interpolate-folder-path` feature is enabled.";
|
|
164
159
|
}
|
readme.md
CHANGED
|
@@ -97,8 +97,7 @@ Compress each file when embedding into the binary. Compression is done via [`inc
|
|
|
97
97
|
## Usage
|
|
98
98
|
|
|
99
99
|
```rust
|
|
100
|
-
#[macro_use]
|
|
101
|
-
|
|
100
|
+
use rust_embed::RustEmbed;
|
|
102
101
|
|
|
103
102
|
#[derive(RustEmbed)]
|
|
104
103
|
#[folder = "examples/public/"]
|
|
@@ -132,6 +131,10 @@ Note: To run the `rocket` example, add the `nightly` feature flag and run on a n
|
|
|
132
131
|
|
|
133
132
|
`cargo +nightly run --example rocket --features nightly`
|
|
134
133
|
|
|
134
|
+
Note: To run the `warp` example:
|
|
135
|
+
|
|
136
|
+
`cargo run --example warp --features warp-ex`
|
|
137
|
+
|
|
135
138
|
## Testing
|
|
136
139
|
|
|
137
140
|
debug: `cargo test --test lib`
|
src/lib.rs
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
#[cfg(all(debug_assertions, not(feature = "debug-embed")))]
|
|
2
|
-
extern crate walkdir;
|
|
3
|
-
|
|
4
|
-
#[cfg(feature = "compression")]
|
|
5
|
-
extern crate include_flate;
|
|
6
1
|
#[cfg(feature = "compression")]
|
|
7
2
|
#[cfg_attr(feature = "compression", doc(hidden))]
|
|
8
3
|
pub use include_flate::flate;
|
|
@@ -23,8 +18,8 @@ pub extern crate rust_embed_utils as utils;
|
|
|
23
18
|
///
|
|
24
19
|
/// This trait is meant to be derived like so:
|
|
25
20
|
/// ```
|
|
26
|
-
/// #[macro_use]
|
|
27
|
-
///
|
|
21
|
+
/// use rust_embed::RustEmbed;
|
|
22
|
+
///
|
|
28
23
|
/// #[derive(RustEmbed)]
|
|
29
24
|
/// #[folder = "examples/public/"]
|
|
30
25
|
/// struct Asset;
|
tests/interpolated_path.rs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
#[macro_use]
|
|
2
|
-
|
|
1
|
+
use rust_embed::RustEmbed;
|
|
3
2
|
|
|
4
3
|
/// Test doc comment
|
|
5
4
|
#[derive(RustEmbed)]
|
|
@@ -8,17 +7,14 @@ struct Asset;
|
|
|
8
7
|
|
|
9
8
|
#[test]
|
|
10
9
|
fn get_works() {
|
|
11
|
-
|
|
10
|
+
if Asset::get("index.html").is_none() {
|
|
12
|
-
|
|
11
|
+
panic!("index.html should exist");
|
|
13
|
-
_ => assert!(true),
|
|
14
12
|
}
|
|
15
|
-
|
|
13
|
+
if Asset::get("gg.html").is_some() {
|
|
16
|
-
|
|
14
|
+
panic!("gg.html should not exist");
|
|
17
|
-
_ => assert!(true),
|
|
18
15
|
}
|
|
19
|
-
|
|
16
|
+
if Asset::get("images/llama.png").is_none() {
|
|
20
|
-
|
|
17
|
+
panic!("llama.png should exist");
|
|
21
|
-
_ => assert!(true),
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
20
|
|
tests/lib.rs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
#[macro_use]
|
|
2
|
-
|
|
1
|
+
use rust_embed::RustEmbed;
|
|
3
2
|
|
|
4
3
|
/// Test doc comment
|
|
5
4
|
#[derive(RustEmbed)]
|
|
@@ -8,17 +7,14 @@ struct Asset;
|
|
|
8
7
|
|
|
9
8
|
#[test]
|
|
10
9
|
fn get_works() {
|
|
11
|
-
|
|
10
|
+
if Asset::get("index.html").is_none() {
|
|
12
|
-
|
|
11
|
+
panic!("index.html should exist");
|
|
13
|
-
_ => assert!(true),
|
|
14
12
|
}
|
|
15
|
-
|
|
13
|
+
if Asset::get("gg.html").is_some() {
|
|
16
|
-
|
|
14
|
+
panic!("gg.html should not exist");
|
|
17
|
-
_ => assert!(true),
|
|
18
15
|
}
|
|
19
|
-
|
|
16
|
+
if Asset::get("images/llama.png").is_none() {
|
|
20
|
-
|
|
17
|
+
panic!("llama.png should exist");
|
|
21
|
-
_ => assert!(true),
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
20
|
|
utils/Cargo.toml
CHANGED
|
@@ -9,6 +9,7 @@ license = "MIT"
|
|
|
9
9
|
keywords = ["http", "rocket", "static", "web", "server"]
|
|
10
10
|
categories = ["web-programming::http-server"]
|
|
11
11
|
authors = ["pyros2097 <pyros2097@gmail.com>"]
|
|
12
|
+
edition = "2018"
|
|
12
13
|
|
|
13
14
|
[dependencies]
|
|
14
15
|
walkdir = "2.2.7"
|
utils/src/lib.rs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
#[cfg(all(debug_assertions, not(feature = "debug-embed")))]
|
|
2
|
-
extern crate walkdir;
|
|
3
|
-
|
|
4
1
|
#[cfg_attr(all(debug_assertions, not(feature = "debug-embed")), allow(unused))]
|
|
5
2
|
pub struct FileEntry {
|
|
6
3
|
pub rel_path: String,
|