Cannot move out of an `Arc` - rust

I have a struct called routing with the following methods.
#[derive(Clone)]
pub struct Routing {
get_routes: Node<PyFunction>,
post_routes: Node<PyFunction>,
put_routes: Node<PyFunction>,
delete_routes: Node<PyFunction>,
patch_routes: Node<PyFunction>,
head_routes: Node<PyFunction>,
options_routes: Node<PyFunction>,
connect_routes: Node<PyFunction>,
trace_routes: Node<PyFunction>,
}
impl Routing {
pub fn new(router: &Router) -> Routing {
let get_routes = Router::protocol_to_tree(&router.get_routes);
let post_routes = Router::protocol_to_tree(&router.post_routes);
let put_routes = Router::protocol_to_tree(&router.put_routes);
let delete_routes = Router::protocol_to_tree(&router.delete_routes);
let patch_routes = Router::protocol_to_tree(&router.patch_routes);
let head_routes = Router::protocol_to_tree(&router.head_routes);
let options_routes = Router::protocol_to_tree(&router.options_routes);
let connect_routes = Router::protocol_to_tree(&router.connect_routes);
let trace_routes = Router::protocol_to_tree(&router.trace_routes);
Self {
get_routes,
post_routes,
put_routes,
delete_routes,
patch_routes,
head_routes,
options_routes,
connect_routes,
trace_routes,
}
}
#[inline(always)]
fn get_relevant_map(self, route: &Method) -> Option<Node<PyFunction>> {
match route {
&Method::GET => Some(self.get_routes),
&Method::POST => Some(self.post_routes),
&Method::PUT => Some(self.put_routes),
&Method::PATCH => Some(self.patch_routes),
&Method::DELETE => Some(self.delete_routes),
&Method::HEAD => Some(self.head_routes),
&Method::OPTIONS => Some(self.options_routes),
&Method::CONNECT => Some(self.connect_routes),
&Method::TRACE => Some(self.trace_routes),
_ => None,
}
}
#[inline(always)]
pub fn get_route(self, route_method: &Method, route: &str) -> Option<PyFunction> {
println!("Hello world how are your");
let table = self.get_relevant_map(route_method)?;
let x = match table.at(route) {
Ok(res) => Some(res.value.clone()),
Err(_) => None,
};
x
}
}
and I am trying to access call the get_route method of the implementation, but I am getting an error.
async fn index(
router: web::Data<Arc<Routing>>,
headers: web::Data<Arc<Headers>>,
mut payload: web::Payload,
req: HttpRequest,
) -> impl Responder {
let x = match (&router)
.clone()
.get_route(&req.method().clone(), req.uri().path())
.clone()
{
Some(handler_function) => {
return handle_request(&handler_function, &headers, &mut payload, &req).await
}
None => {
let mut response = HttpResponse::Ok();
apply_headers(&mut response, &headers);
return response.finish();
}
};
x
}
[rustc E0507] [E] cannot move out of an `Arc`
move occurs because value has type `router::Routing`, which does not implement the `Copy` trait
Complete error message:
error[E0507]: cannot move out of an `Arc`
--> src/server.rs:160:19
|
160 | let x = match (&router)
| ___________________^
161 | | .clone()
| |________________^ move occurs because value has type `Routing`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors; 2 warnings emitted
Some errors have detailed explanations: E0308, E0507.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `robyn`
I have tried wrapping the properties of the struct in Arc, Locks but still am unable to figure out the solution.
Any help would be highly appreciated. Thanks in advance.

Related

rust async trait with coroutine

I develop an update system in rust. It create patches between 2 binaries. You can download binaries or patches and install it. Patches and binaries are compressed. The client download compressed files and decompress it
I do
#[async_trait]
impl<'a> Stream for UpdatePackageStream<'a> {
type Item = Result<SharedUpdateProgress, UpdateError>;
async fn poll_next(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
let download_poll = this.download_stream.poll_next_unpin(cx);
let apply_poll = this.apply_stream.poll_next_unpin(cx);
match (download_poll, apply_poll) {
(Poll::Ready(None), Poll::Ready(None)) => Poll::Ready(None),
(Poll::Pending, Poll::Pending) => Poll::Pending,
(Poll::Pending, Poll::Ready(None)) => Poll::Pending,
(Poll::Ready(None), Poll::Pending) => Poll::Pending,
(Poll::Ready(Some(Err(err))), _) => {
// Download errors cause the apply thread to be cancelled
this.apply_stream.cancel();
Poll::Ready(Some(Err(err)))
}
(download_poll, apply_poll) => {
let mut delta = Progression::default();
if let Poll::Ready(Some(Ok(download_progress))) = download_poll {
this.state.borrow_mut().available = download_progress.available;
let mut state = this.shared_state.lock().await;
state.downloading_operation_idx = download_progress.available.operation_idx;
delta.downloaded_files = download_progress.delta_downloaded_files;
delta.downloaded_bytes = download_progress.delta_downloaded_bytes;
this.apply_stream.notify(download_progress.available);
}
if let Poll::Ready(Some(apply_progress)) = apply_poll {
match apply_progress {
Ok(apply_progress) => {
this.state.borrow_mut().applied.operation_idx =
apply_progress.operation_idx;
let mut state = this.shared_state.lock().await; // note the await here, so the closure must be async
state.applying_operation_idx = apply_progress.operation_idx;
delta.applied_files = apply_progress.delta_applied_files;
delta.applied_input_bytes = apply_progress.delta_input_bytes;
delta.applied_output_bytes = apply_progress.delta_output_bytes;
}
Err(ApplyError::OperationFailed { path, slice, cause }) => {
warn!("{} failed: {}", path, cause);
let mut state = this.state.borrow_mut();
state.failures.push(match slice {
Some(slice) => metadata::v1::Failure::Slice { path, slice },
None => metadata::v1::Failure::Path { path },
});
delta.failed_files = 1;
}
Err(ApplyError::Cancelled) => {}
Err(ApplyError::PoisonError) => {
return Poll::Ready(Some(Err(UpdateError::PoisonError)))
}
}
}
`` {
let mut state = this.shared_state.lock().await;
state.inc_progress(delta);
}
Poll::Ready(Some(Ok(this.shared_state.clone())))
}
}
}
}
But get
error[E0195]: lifetime parameters or bounds on method `poll_next` do not match the trait declaration
--> lib/src/workspace/updater.rs:143:14
|
143 | async fn poll_next(
| ______________^
144 | | self: Pin<&mut Self>,
145 | | cx: &mut std::task::Context<'_>,
146 | | ) -> Poll<Option<Self::Item>> {
| |_____^ lifetimes do not match method in trait
Stream is from future::stream::Stream
Without async_trait and the 2 async fn, the fn and my app build without issue.
If I use std::sync::Mutex instead of tokio::sync::Mutex, I get
let state = update_state.lock();
| ----- has type `std::sync::MutexGuard<'_, UpdateProgress>` which is not `Send`
...
273 | let res = update_stream.try_for_each(|_state| future::ready(Ok(()))).await;
| ^^^^^^ await occurs here, with `state` maybe used later
...
305 | }
| - `state` is later dropped here
= note: required for the cast from `impl futures::Future<Output = Result<tonic::Response<BuildOutput>, Status>>` to the object type `dyn futures::Future<Output = Result<tonic::Response<BuildOutput>, Status>> + std::marker::Send`
UpdateProgress is a simple struct.
I don't inderstand why I get these issues and don't know how to fix them

What signature can I use to download files using Axum and Tokio?

I'm using axum and this code (found here) to download files:
use axum::{
body::StreamBody,
http::{header, StatusCode},
response::{Headers, IntoResponse},
routing::get,
Router,
};
use std::net::SocketAddr;
use tokio_util::io::ReaderStream;
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(handler));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
async fn handler() -> impl IntoResponse {
// `File` implements `AsyncRead`
let file = match tokio::fs::File::open("Cargo.toml").await {
Ok(file) => file,
Err(err) => return Err((StatusCode::NOT_FOUND, format!("File not found: {}", err))),
};
// convert the `AsyncRead` into a `Stream`
let stream = ReaderStream::new(file);
// convert the `Stream` into an `axum::body::HttpBody`
let body = StreamBody::new(stream);
let headers = Headers([
(header::CONTENT_TYPE, "text/toml; charset=utf-8"),
]);
Ok((headers, body))
}
Everything works. But I cannot find a way to move the below code in a separate function:
let file = match tokio::fs::File::open("Cargo.toml").await {
Ok(file) => file,
Err(err) => return Err((StatusCode::NOT_FOUND, format!("File not found: {}", err))),
};
I would like to use both tokio::fs::File and https://crates.io/crates/rust-s3 methods in this function.
So I need a "common type" which appear to be AsyncRead, I think.
What should be the signature of the function?
I tried with:
use tokio::io::AsyncRead;
pub struct Player {
db: Arc<DB>
}
impl Handler {
pub async fn player_pdf(
&self,
id: &str,
) -> Result<&(dyn AsyncRead)> {
//...use id here...
let file = &tokio::fs::File::open("player.pdf").await?;
Ok(file)
}
}
but I get the error:
error[E0308]: mismatched types
|
55 | Ok(file)
| -- ^^^^
| | |
| | expected reference, found struct `tokio::fs::File`
| | help: consider borrowing here: `&file`
| arguments to this enum variant are incorrect
|
= note: expected reference `&dyn tokio::io::AsyncRead`
found struct `tokio::fs::File`
I tried with: let file = &tokio::fs::File::open("player.pdf").await?; and I got:
error[E0515]: cannot return value referencing temporary value
|
43 | let file = &tokio::fs::File::open(...
| --------------------------- temporary value created here
...
55 | Ok(file)
| ^^^^^^^^ returns a value referencing data owned by the current function
What can I use?
Returning a generic "boxed" value might be the solution here:
impl Handler {
pub async fn player_pdf(
&self,
id: &str,
) -> Result<Box<dyn AsyncRead>> {
//...use id here...
Ok(Box::new(tokio::fs::File::open("player.pdf").await?))
}
}
Where now there's no dangling reference, it's encapsulated and fully owned.

Use hyper to pass IP address of incoming connection to stack of Services

I am trying to write a server using hyper that will pass the remote (client) address of the incoming connection down to a stack of Layers (that I have built using ServiceBuilder.
I have tried to use examples from the hyper docs and also this example from the Rust forums; however, these both
pass down data to a single handler function, not a stack of service layers
have a return type of Result<Response, Infallible>, which I don't want (I want to be able to drop a connection without returning a response).
Here is one of my tries (I have tried several approaches):
use std::{
net::SocketAddr,
time::Duration,
};
use hyper::{
Body, Request, Response, Server,
server::conn::AddrStream,
service::{
make_service_fn,
service_fn,
},
};
use tower::{
Service, ServiceBuilder,
timeout::TimeoutLayer,
};
async fn dummy_handle(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
let response_text = format!(
"{:?} {} {}", req.version(), req.method(), req.uri()
);
let response = Response::new(Body::from(response_text));
Ok(response)
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
// Dummy stack of service layers I want to wrap.
let service = ServiceBuilder::new()
.layer(TimeoutLayer::new(Duration::from_millis(1000 * 60)))
.service_fn(dummy_handle);
let make_svc = make_service_fn(|socket: &AddrStream| {
let remote_addr = socket.remote_addr();
let mut inner_svc = service.clone();
let outer_svc = service_fn(move |mut req: Request<Body>| async {
req.extensions_mut().insert(remote_addr);
inner_svc.call(req)
});
async move { outer_svc }
});
Server::bind(&addr)
.serve(make_svc)
.await?;
Ok(())
}
I understand full well that including error messages is helpful here; however, this is one of those cases where the Rust compiler spits out pages (or at least screenfuls) of cryptic stuff, so I am going to limit myself to a couple of choice examples.
First, I get this a lot:
type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == Result<_, _>`
for example, preceding this:
39 | let outer_svc = service_fn(move |mut req: Request<Body>| async {
| _____________________________________-___________________________________-
| | ____________________________________|
| ||
40 | || req.extensions_mut().insert(remote_addr);
41 | || inner_svc.call(req)
42 | || });
| || -
| ||_________|
| |__________the expected closure
| the expected `async` block
...
48 | .serve(make_svc)
| ----- ^^^^^^^^ expected struct `service::util::ServiceFn`, found enum `Result`
| |
| required by a bound introduced by this call
And then the very next error message seems to be entirely contradictory:
[ several lines identical to above elided here ]
48 | .serve(make_svc)
| ^^^^^ expected enum `Result`, found struct `service::util::ServiceFn`
I just can't figure out what the compiler wants from me.
Try this:
use std::{net::SocketAddr, time::Duration, convert::Infallible};
use hyper::{
server::conn::AddrStream,
service::{make_service_fn, service_fn},
Body, Request, Response, Server,
};
use tower::{Service, ServiceBuilder};
async fn dummy_handle(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
let response_text = format!("{:?} {} {}", req.version(), req.method(), req.uri());
let response = Response::new(Body::from(response_text));
Ok(response)
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
// Dummy stack of service layers I want to wrap.
let service = ServiceBuilder::new()
.timeout(Duration::from_millis(1000 * 60))
.service_fn(dummy_handle);
let make_svc = make_service_fn(|socket: &AddrStream| {
let remote_addr = socket.remote_addr();
let mut inner_svc = service.clone();
let outer_svc = service_fn(move |mut req: Request<Body>| {
req.extensions_mut().insert(remote_addr);
inner_svc.call(req)
});
async { Ok::<_, Infallible>(outer_svc) }
});
Server::bind(&addr).serve(make_svc).await?;
Ok(())
}
You were returning a future that returns another future:
|| async {
req.extensions_mut().insert(remote_addr);
inner_svc.call(req)
}
This is an Future<Output = Future<...>>.
Therefore, you need to turn your closure into this:
|| {
req.extensions_mut().insert(remote_addr);
inner_svc.call(req)
}
If you do not need ServiceBuilder then you can do:
use std::{
net::SocketAddr,
};
use std::convert::Infallible;
use hyper::{
Body, Request, Response, Server,
server::conn::AddrStream,
service::{
make_service_fn,
service_fn,
},
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>>
{
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
let make_svc = make_service_fn(|socket: &AddrStream| {
let remote_addr = socket.remote_addr();
async move {
Ok::<_, Infallible>(service_fn(move |req: Request<Body>| async move {
println!("remote_addr: {:?}, request: {:?}", remote_addr, req);
Ok::<_, Infallible>(
Response::new(Body::from(format!(
"{:?} {} {}", req.version(), req.method(), req.uri()
)))
)
}))
}
});
let _ = Server::bind(&addr).serve(make_svc).await?;
Ok(())
}
else
use std::{
net::SocketAddr,
time::Duration,
task::{Context, Poll},
future::Future,
pin::Pin
};
use hyper::{
http,
Body, Request, Response, Server
};
use tower::{
timeout::TimeoutLayer,
Service, ServiceBuilder,
};
#[derive(Debug)]
pub struct CustomService;
impl Service<Request<Body>> for CustomService {
type Response = Response<Body>;
type Error = http::Error;
type Future = Pin<Box<dyn Future<Output=Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { Poll::Ready(Ok(())) }
fn call(&mut self, req: Request<Body>) -> Self::Future {
let rsp = Response::builder();
let body = Body::from(format!("{:?} {} {}", req.version(), req.method(), req.uri()));
let rsp = rsp.status(200).body(body).unwrap();
Box::pin(async {Ok(rsp) })
}
}
#[derive(Debug)]
pub struct MakeService;
impl<T> Service<T> for MakeService {
type Response = CustomService;
type Error = std::io::Error;
type Future = Pin<Box<dyn Future<Output=Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { Ok(()).into() }
fn call(&mut self, _: T) -> Self::Future {
Box::pin(async { Ok(CustomService) })
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>>
{
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
let service = ServiceBuilder::new()
.layer(TimeoutLayer::new(Duration::from_secs(60)))
.service(MakeService);
let _ = Server::bind(&addr).serve(service).await?;
Ok(())
}

How to write an asynchronous recursive walkdir function with an asynchronous callback

I'm trying to write an async function that will traverse the filesystem tree, recursively, and calls an asynchronous callback for each file found.
This is for a learning effort, I have no real use case.
Here is what I have so far:
use async_std::{
fs::{self, *},
path::*,
prelude::*,
}; // 1.5.0, features = ["unstable"]
use futures::{
executor::block_on,
future::{BoxFuture, FutureExt},
}; // 0.3.4
use std::{marker::Sync, pin::Pin};
fn main() {
fn walkdir<F>(path: String, cb: &'static F) -> BoxFuture<'static, ()>
where
F: Fn(&DirEntry) -> BoxFuture<()> + Sync + Send,
{
async move {
let mut entries = fs::read_dir(&path).await.unwrap();
while let Some(path) = entries.next().await {
let entry = path.unwrap();
let path = entry.path().to_str().unwrap().to_string();
if entry.path().is_file().await {
cb(&entry).await
} else {
walkdir(path, cb).await
}
}
}
.boxed()
}
let foo = async {
walkdir(".".to_string(), &|entry: &DirEntry| async {
async_std::println!(">> {}\n", &entry.path().to_str().unwrap()).await
})
.await
};
block_on(foo);
}
I get this far by some sort of trial and error, but now I'm stuck on async closure callback with this error
warning: unused import: `path::*`
--> src/main.rs:3:5
|
3 | path::*,
| ^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused import: `pin::Pin`
--> src/main.rs:10:25
|
10 | use std::{marker::Sync, pin::Pin};
| ^^^^^^^^
error[E0308]: mismatched types
--> src/main.rs:33:54
|
33 | walkdir(".".to_string(), &|entry: &DirEntry| async {
| ______________________________________________________^
34 | | async_std::println!(">> {}\n", &entry.path().to_str().unwrap()).await
35 | | })
| |_________^ expected struct `std::pin::Pin`, found opaque type
|
= note: expected struct `std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = ()> + std::marker::Send>>`
found opaque type `impl core::future::future::Future`
use async_std::{
fs::{self, *},
path::*,
prelude::*,
}; // 1.5.0
use futures::{future::{Future, FutureExt, LocalBoxFuture}, executor}; // 0.3.4
fn main() {
async fn walkdir<R>(path: impl AsRef<Path>, mut cb: impl FnMut(DirEntry) -> R)
where
R: Future<Output = ()>,
{
fn walkdir_inner<'a, R>(path: &'a Path, cb: &'a mut dyn FnMut(DirEntry) -> R) -> LocalBoxFuture<'a, ()>
where
R: Future<Output = ()>,
{
async move {
let mut entries = fs::read_dir(path).await.unwrap();
while let Some(path) = entries.next().await {
let entry = path.unwrap();
let path = entry.path();
if path.is_file().await {
cb(entry).await
} else {
walkdir_inner(&path, cb).await
}
}
}.boxed_local()
}
walkdir_inner(path.as_ref(), &mut cb).await
}
executor::block_on({
walkdir(".", |entry| async move {
async_std::println!(">> {}", entry.path().display()).await
})
});
}
Notable changes:
Take in AsRef<Path> instead of a String and a generic closure instead of a trait object reference
Change the closure type to be FnMut as it's more permissive
The closure returns any type that is a future.
There's an inner implementation function that hides the ugly API required for recursive async functions.
The callback takes the DirEntry by value instead of by reference.
See also:
How to asynchronously explore a directory and its sub-directories?
How to using async fn callback in rust

Borrowing error using macros

I'm trying to use the code I found here with some problems, basically it's a borrowing error using some macros, the error:
Compiling playground v0.0.1 (file:///playground)
error[E0597]: `body` does not live long enough
--> src/main.rs:12:3
|
6 | let raw_structure = borrow_function(&body);
| ---- borrow occurs here
...
12 | }
| ^ `body` dropped here while still borrowed
...
31 | let body = get_body_as!(&str, "Hello", function1);
| -------------------------------------- in this macro invocation
32 | println!("Hello");
33 | }
| - borrowed value needs to live until here
I manage to create a Minimal, Complete, and Verifiable example, I was thinking that a solution would be to transform the macros into functions, but I'm not completely sure how to do that either (Playground
):
macro_rules! get_body_as {
($structure:ty, $req:expr, $error_fn:ident) => {
{
let body = get_body!($req, $error_fn);
let raw_structure = borrow_function(&body);
match raw_structure {
Ok(structure) => structure,
Err(error) => "Error"
}
}
}
}
macro_rules! get_body {
($req:expr, $error_fn:ident) => {
{
let mut payload = String::new();
payload
}
}
}
fn borrow_function(s: &str) -> Result<&str, &str> {
Ok(s)
}
fn main() {
let function1 = |s: &str| s;
let body = get_body_as!(&str, "Hello", function1);
println!("Hello");
}
The problem is that you are trying to return a reference to a body variable from a block which owns the body variable, but body is to be dropped at the end of that block, so the reference would outlive the data it references.
If you want your example to compile, you can alter your code so that body is declared within the main function using ident parameter added to get_body_as macro:
macro_rules! get_body_as {
($structure:ty, $req:expr, $error_fn:ident, $body: ident) => {
let $body = get_body!($req, $error_fn);
let raw_structure = borrow_function(&$body);
match raw_structure {
Ok(structure) => structure,
Err(error) => "Error"
}
}
}
macro_rules! get_body {
($req:expr, $error_fn:ident) => {
{
let mut payload = String::new();
payload
}
}
}
fn borrow_function(s: &str) -> Result<&str, &str> {
Ok(s)
}
fn main() {
let function1 = |s: &str| s;
get_body_as!(&str, "Hello", function1, body);
println!("Hello");
}
This example compiles, but still has warnings about unused variables, I have made only minimal changes for compilation to succeed.

Resources