I am using rust rocket rocket = { version = "=0.5.0-rc.2", features = ["json"] } as my web server, today I found there is two way to start the rocket, one of the start like this:
#[rocket::main]
async fn main() {
// the rocket start logic
}
the other way look like this:
#[launch]
async fn rocket() -> _ {
// the rocket start logic
}
which one style should I use? which one is better? what should I learn from the two startup style? I am search from google but no one talk about this.
As stated in the documentation, #[rocket::main]
should be used only when the return values of ignite() or launch() are to be inspected
If you use rust-analyzer #[rocket::main] is reliably discovered as the main function which brings the added benefit, that convenient Debug and Run buttons are displayed above the function.
For production it would however be recommended to use the #[launch] attribute.
Related
I need to make a function that will receive an HTML page from the link. Since I use the yew library, WASM does not allow me to use many custom libraries and functions. For example, the library Tokio, future and the function reqwest::blocking::get().
I had something like this code that works in the Rust test file:
pub fn get_response() {
let link = "url";
let response = reqwest::blocking::get(link).unwrap();
let res = response.text().unwrap();
}
But as I said, the yew library does not allow me to use blocking::get() how do I make the same function but without using blocking::get()?
If you are using Yew, then your Rust code will always be running within the context of a component or in service there-of. So you should have access to a Context or at least a Scope and then can issue async tasks like so:
ctx.link().send_future(async move {
// do your reqwest call here
});
There are slightly different but similar functions like .callback_future(), .callback_future_once(), and .send_future_batch() but are really only different in terms of how they are called or how they interact with Yew. And with almost all scope functions, these will expect to return some message to the component, since you're likely to want to update some state after receiving the response.
If you really don't want to use Yew's scope functions, or don't have a reasonable way to access them, you can use spawn_local from the wasm-bindgen-futures crate that Yew uses internally:
wasm_bindgen_futures::spawn_local(async move {
// do your reqwest call here
})
I've been working on a fairly basic project which needs to interact with fonts. The plan was to use the bindings for FreeType by the Servo team. However, I'm having a hard time figuring out how exactly one is to use it. I've new to FreeType, so I'm following their tutorial. What's tripping me up at this point is creating the handles. I did try the (admittedly laughable) to create the library handle for instance:
use freetype::freetype;
let library: freetype::FT_Library;
That predictably did not work. I have resolved to use font_kit for the project because I'm fairly certain this is a bit over my head. But I'd still love to find out how I can actually do this.
It looks like you can use std::ptr::null_mut to initialize freetype::freetype::FT_Library:
fn main() {
let mut lib: freetype::freetype::FT_Library = std::ptr::null_mut();
let result = unsafe {
freetype::freetype::FT_Init_FreeType(&mut lib)
};
println!("Initialization succeed:{}", freetype::succeeded(result));
}
Based on example.
The docs on how to use existing javascript web systems within a rust -> wasm flow using wasm-bindgen are pretty straight-forward. In short:
List the needed features as dependencies
// cargo.toml
[dependencies.web-sys]
version = "0.3.4"
features = [
'AudioContext',
'OscillatorNode'
]
Access through web_sys, and treat them as normal from there.
// lib.rs
#[wasm_bindgen]
impl FmOsc {
#[wasm_bindgen(constructor)]
pub fn new() -> Result<FmOsc, JsValue> {
let ctx = web_sys::AudioContext::new()?;
let primary = ctx.create_oscillator()?;
let fm_osc = ctx.create_oscillator()?;
Link to full example
While this approach works for most web systems, it is not so simple for ones which require you to extend a class. In this case I'm trying to use the AudioWorkletProccessor from wasm-bindgen
In standard usage, you are supposed to extend the AudioWorkletProcessor class, then register it. MDN Example
How can I approach this problem? First I need to extend AudioWorkletProcessor in Rust (which doesn't do normal classes and inheritance), overriding its process() function. Then I need to make sure registerProcessor() is injected into my rust space.
EDIT: WASM docs on extends
You will have to do that on the JavaScript side. wasm-bindgen does not support extending imported classes and re-exporting them to JavaScript; however, they do want to support it eventually and there is an issue to track it, and a related RFC.
I'm implementing a REST API using actix-web and mongodb for the data back-end. I am using version 1.1.1 of the official rust-mongodb driver from crates.io and Rust 1.46.
If I add code to make a call to the mongodb collection to get records for example, even though cargo check shows no errors or warnings, cargo build takes a long time and then terminates with an error that it could not compile my project and a (signal 9, SIGKILL: kill). After searching for the problem, I get that this is probably an out of memory error caused during the build/linking process. I am working on a Debian 10 machine with 16GB of RAM, so this is not very reasonable.
This only happens when I make the call in code inside a "handler" using async and await.
For example, if I try to get the names of the sample collection like so:
pub async fn samples() -> Result<HttpResponse, Error> {
let dbnames = get_samples().await;
Ok(HttpResponse::Ok().json(dbnames.unwrap()))
}
async fn get_samples() -> Result<Vec<String>, ServiceError> {
let mut dbnames: Vec<String> = Vec::new();
let client_uri = String::from("mongodb+srv://<...MONGODB_CONNECTION_INFO...>/sample_mflix?retryWrites=true&w=majority");
let client = mongodb::Client::with_uri_str(client_uri.as_ref()).await?;
for name in client.list_database_names(None, None).await? {
dbnames.push(format!("- {}", name));
}
Ok(dbnames)
}
The cargo build will never complete and will stop with the aforementioned error.
Just to make sure, I used code to get the sample collection names, directly inside main.rs in the main function and it worked with no issues and the compile and build time were reasonable.
let client = mongodb::Client::with_uri_str(client_uri.as_ref()).await;
println!("Databases:");
for name in client.unwrap().list_database_names(None, None).await {
for item in name {
println!("- {}", item);
}
}
Same result even if use cargo build --release to avoid having too much debug info
This only happens when using the async API of the rust-mongodb driver. With the sync API everything build and works properly.
What could be the cause of this?
I got the exactly the same issue after upgrade to 1.1.1 with async API. cargo build will never complete, it will consume 100% CPU and will keep consuming memory until exhausted.
Found related issues:
https://jira.mongodb.org/browse/RUST-558
https://github.com/actix/actix-web/issues/1688
https://github.com/rust-lang/rust/issues/75992
Two ways to workaround:
Downgrade to rust 1.45.2
Switch to async-std-runtime to workaround this issue. mongodb = { version = "1.1.1", default-features = false, features = ["async-std-runtime"] }
There is so much outdated information, it is really hard to find out how to sleep. I'd like something similar to this Java code:
Thread.sleep(4000);
Rust 1.4+
Duration and sleep have returned and are stable!
use std::{thread, time::Duration};
fn main() {
thread::sleep(Duration::from_millis(4000));
}
You could also use Duration::from_secs(4), which might be more obvious in this case.
The solution below for 1.0 will continue to work if you prefer it, due to the nature of semantic versioning.
Rust 1.0+
Duration wasn't made stable in time for 1.0, so there's a new function in town - thread::sleep_ms:
use std::thread;
fn main() {
thread::sleep_ms(4000);
}
Updated answer
This is the updated code for the current Rust version:
use std::time::Duration;
use std::thread::sleep;
fn main() {
sleep(Duration::from_millis(2));
}
Rust play url: http://is.gd/U7Oyip
Old answer pre-1.0
According the pull request https://github.com/rust-lang/rust/pull/23330 the feature that will replace the old std::old_io::timer::sleep is the new std::thread::sleep.
Pull request description on GitHub:
This function is the current replacement for std::old_io::timer which
will soon be deprecated. This function is unstable and has its own
feature gate as it does not yet have an RFC nor has it existed for
very long.
Code example:
#![feature(std_misc, thread_sleep)]
use std::time::Duration;
use std::thread::sleep;
fn main() {
sleep(Duration::milliseconds(2));
}
This uses sleep and Duration, which are currently behind the feature gates of thread_sleep and std_misc, respectively.