An opened image as a global variable? - rust

I'd like to write a server that resizes a huge image. Since loading it on every request would take a lot of time, I decided to pre-load it. Unfortunately I got the following error:
Compiling hello_world v0.0.0 (/tmp/Rocket/examples/hello_world)
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> examples/hello_world/src/main.rs:9:35
|
9 | static img: image::DynamicImage = image::open("/home/d33tah/tmp/combined.png").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> examples/hello_world/src/main.rs:9:35
|
9 | static img: image::DynamicImage = image::open("/home/d33tah/tmp/combined.png").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.
error: Could not compile `hello_world`.
To learn more, run the command again with --verbose.
Here's the code:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[cfg(test)] mod tests;
extern crate image;
static img: image::DynamicImage = image::open("/home/d33tah/tmp/combined.png").unwrap();
#[get("/")]
fn hello() -> Vec<u8> {
"".into()
}
fn main() {
rocket::ignite().mount("/", routes![hello]).launch();
}
To compile it, you'll need rocket installed based on its latest Github checkout (currently: 831d8dfbe30dd69f0367a75361e027127b2100e1) and image crate.
Is it possible to create such a global variable? If not, do I have any other options?
EDIT: this was flagged as a duplicate of this question, but as Boiethios showed, this specific case is better solved by Rocket's API.

If you want to share something in Rocket, you will have to use a managed state:
Say to Rocket you want to manage the resource:
let image = image::open("/home/d33tah/tmp/combined.png").unwrap();
rocket::ignite().manage(image);
Retrieve it in the routes where you need it:
#[get("/foo")]
fn foo(image: State<DynamicImage>) {
// Can use `image`.
}

Related

Why do I need to "use std" in a module but not at the root of my crate? [duplicate]

I have the following code:
pub mod a {
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
I get errors when I compile this:
error[E0433]: failed to resolve. Use of undeclared type or module `std`
--> src/main.rs:4:24
|
4 | println!("{}", std::fs::remove_file("Somefilehere"));
| ^^^ Use of undeclared type or module `std`
However, removing the inner module and compiling the code it contains by itself works fine:
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
What am I missing here? I get the same errors if the module is in a separate file:
main.rs
pub mod a;
a.rs
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
By default, the compiler inserts extern crate std; at the beginning of the crate root (the crate root is the file that you pass to rustc). This statement has the effect of adding the name std to the crate's root namespace and associating it with a module that contains the public contents of the std crate.
However, in child modules, std is not automatically added in the module's namespace. This is why the compiler cannot resolve std (or anything that starts with std::) in a module.
There are many ways to fix this. First, you can add use std; in a module to make the name std refer, within that module, to the root std. Note that in use statements, the path is treated as absolute (or "relative to the crate's root namespace"), whereas everywhere else, paths are treated as relative to the current namespace (be it a module, a function, etc.).
pub mod a {
use std;
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
You can also use a use statement to import more specific items. For example, you can write use std::fs::remove_file;. This lets you avoid having to type the whole path to remove_file and just use the name remove_file directly within that module:
pub mod a {
use std::fs::remove_file;
#[test]
pub fn test() {
println!("{:?}", remove_file("Somefilehere")));
}
}
Finally, you can avoid using use altogether by prefixing the path with :: to ask the compiler to resolve the path from the crate's root namespace (i.e. turning the path into an absolute path).
pub mod a {
#[test]
pub fn test() {
println!("{:?}", ::std::fs::remove_file("Somefilehere"));
}
}
The recommended practice is to import types (structs, enums, etc.) directly (e.g. use std::rc::Rc;, then use the path Rc), but to use functions through an import of their parent module (e.g. use std::io::fs;, then use the path fs::remove_file).
pub mod a {
use std::fs;
#[test]
pub fn test() {
println!("{:?}", fs::remove_file("Somefilehere"));
}
}
Side note: You can also write self:: at the beginning of a path to make it relative to the current module. This is more often used in use statements, since other paths are already relative (though they are relative to the current namespace, whereas self:: is always relative to the containing module).
Nowadays, std is directly accessible from everywhere, so the code you showed is compiling as you would expect.
Furthermore, extern crate is no longer needed in Rust edition 2018. Adding a dependency to Cargo.toml makes the crate name directly available as a top-level identifier.

Unresolved import when organising Rust code in multiple directories

I am used to organising files in separate directories depending on the problem domain (for example grouping image processing stuff together, IO stuff in another directory etc). I am not sure if this way or organisation is even recommended in Rust.
I have setup my project in multiple directories:
- helloworld
- Cargo.toml
- src
- main.rs
- test
- one.rs
I am trying to use a function from one.rs in main.rs
one.rs
fn test() {
println!("Calling test...");
}
main.rs
use test::one::*;
fn main() {
println!("Hello, world!");
test();
}
This results in a compile time error:
error[E0432]: unresolved import `test::one::*`
--> src/main.rs:1:5
|
1 | use test::one::*;
| ^^^^^^^^^^^^^ Maybe a missing `extern crate test;`?
error[E0425]: cannot find function `test` in this scope
--> src/main.rs:6:5
|
6 | test();
| ^^^^ not found in this scope
Looking at some online projects, it seems like something like this should be possible.
It is possible, however you need to inform your code about additional module that is inside your code using:
mod test;
And then create additional file
// src/test/mod.rs
pub mod one;

Why does using an external crate's function require bringing the dependent trait into scope?

Consider the following code in the official tutorial
extern crate rand;
use rand::Rng;
fn main() {
let secret_number = rand::thread_rng().gen_range(1, 101);
}
The line rand::thread_rng().gen_range(1, 101) is a bit confusing for me since I expect calling rand::thread_rng() to automatically resolve the dependency for the trait it is using.
However I need use rand::Rng; for it to work.
So does this mean that I have to resolve the dependency manually when I want to use some function in 3rd party crate?
Why does using an external crate's function require bringing the dependent trait into scope?
It doesn't. This compiles just fine:
extern crate rand;
fn main() {
let secret_number = rand::thread_rng();
}
You are then trying to call a method from a trait on the return value of that function call. That requires the trait to be in scope, as described in Why do I need to import a trait to use the methods it defines for a type?

Importing a crate into a const block

I'm trying to write a procedural macro that implements a #[derive()] trait for a struct. In the generated implementation code I need to use AnyMap.
To avoid multi crate imports, and based on what I read in some other crate's code (namely Serde) I put my generated code into a const _IMPL_xxx_FOR_xxx : () = { /* generated code */ }; block but it fails to compile.
I was able to replicate my issue with the following code
const BLOCK_1: () = {
extern crate anymap;
use anymap::AnyMap;
};
const BLOCK_2: () = {
extern crate anymap;
use anymap::AnyMap;
};
fn main() {
println!("foo");
}
The compile error I'm getting is the following:
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:3:9
|
3 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:9:9
|
9 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
Is it an issue specific to AnyMap? Would you know of any way to fix this (including maybe a different approach to generating procedural macro code if the pattern I'm using is not recommended?
I can replicate this on the playground using simply
const A: () = {
extern crate core;
use core::option::Option;
};
fn main() {}
However, it appears only the use statement is broken, and I can still use items from core, but I have to name them explicitly each time:
const A: () = {
extern crate core;
do_stuff!(core::option::Option)
};
The reason is that use statements typically assume a path relative to the root, and there is no way to explicitly name the block you are in (self refers to the current module unfortunately).
Here's a better workaround - as I said before, Rust uses self to refer to the current module, so you can just put a module in your code block and then have the use statements reference self.
In your case it would be:
const BLOCK_1: () = {
mod inner {
extern crate anymap;
use self::anymap::AnyMap;
}
};
On the specific issue of making this work for procedural macro, a suggested solution was to reexport the needed crate as part of the crate containing the derive macro (or the one containing the class I'm trying to export) using something like pub extern crate anymap and then use <my_crate>::anymap::AnyMap;

Use of undeclared type or module `std` when used in a separate module

I have the following code:
pub mod a {
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
I get errors when I compile this:
error[E0433]: failed to resolve. Use of undeclared type or module `std`
--> src/main.rs:4:24
|
4 | println!("{}", std::fs::remove_file("Somefilehere"));
| ^^^ Use of undeclared type or module `std`
However, removing the inner module and compiling the code it contains by itself works fine:
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
What am I missing here? I get the same errors if the module is in a separate file:
main.rs
pub mod a;
a.rs
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
By default, the compiler inserts extern crate std; at the beginning of the crate root (the crate root is the file that you pass to rustc). This statement has the effect of adding the name std to the crate's root namespace and associating it with a module that contains the public contents of the std crate.
However, in child modules, std is not automatically added in the module's namespace. This is why the compiler cannot resolve std (or anything that starts with std::) in a module.
There are many ways to fix this. First, you can add use std; in a module to make the name std refer, within that module, to the root std. Note that in use statements, the path is treated as absolute (or "relative to the crate's root namespace"), whereas everywhere else, paths are treated as relative to the current namespace (be it a module, a function, etc.).
pub mod a {
use std;
#[test]
pub fn test() {
println!("{:?}", std::fs::remove_file("Somefilehere"));
}
}
You can also use a use statement to import more specific items. For example, you can write use std::fs::remove_file;. This lets you avoid having to type the whole path to remove_file and just use the name remove_file directly within that module:
pub mod a {
use std::fs::remove_file;
#[test]
pub fn test() {
println!("{:?}", remove_file("Somefilehere")));
}
}
Finally, you can avoid using use altogether by prefixing the path with :: to ask the compiler to resolve the path from the crate's root namespace (i.e. turning the path into an absolute path).
pub mod a {
#[test]
pub fn test() {
println!("{:?}", ::std::fs::remove_file("Somefilehere"));
}
}
The recommended practice is to import types (structs, enums, etc.) directly (e.g. use std::rc::Rc;, then use the path Rc), but to use functions through an import of their parent module (e.g. use std::io::fs;, then use the path fs::remove_file).
pub mod a {
use std::fs;
#[test]
pub fn test() {
println!("{:?}", fs::remove_file("Somefilehere"));
}
}
Side note: You can also write self:: at the beginning of a path to make it relative to the current module. This is more often used in use statements, since other paths are already relative (though they are relative to the current namespace, whereas self:: is always relative to the containing module).
Nowadays, std is directly accessible from everywhere, so the code you showed is compiling as you would expect.
Furthermore, extern crate is no longer needed in Rust edition 2018. Adding a dependency to Cargo.toml makes the crate name directly available as a top-level identifier.

Resources