Asynchronous Projections in Rust - asynchronous

Is it possible to do asynchronous projections in rust?
By a projection, I mean a method on a struct that returns a reference to one of its fields. A minimal synchronous example:
struct Aggregate<T>(T);
impl<T> Aggregate<T> {
fn project(&self) -> &T {
&self.0
}
}
An asynchronous projection should not yield a &T but some Future with output &T. Naively trying to implement such a Future does not work; in the following example, the reference in the Output type &T (rightly so) requires a lifetime.
impl<T> Future for Aggregate<T> {
type Output = &T;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready(self.project())
}
}
A correct implementation would have to look like this:
impl<T> Future for Aggregate<T> {
type Output<'s> = &'s T where T: 's;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output<'_>> {
Poll::Ready(self.project())
}
}
But this clashes with the definition of the Future trait, which does not accept a lifetime for Output:
lifetime parameters or bounds on type `Output` do not match the trait declaration
lifetimes do not match type in trait rustcE0195
Is there any way of getting this to work with the core Future trait, or would a dedicated LendingFuture trait be needed (analogous to how a LendingIterator needs a new, dedicated trait)?
If this is not possible to do with the Future trait, are there workarounds and/or are there plans to provide a LendingFuture in core eventually?
I want to explicitly implement Future for some first-class type, not rely on some type automatically generated by async fn desugaring or on trait objects.
My interest in asynchronous projections comes from exploring asynchronous APIs in the style of bytes::Buf, the chunk method boils down to a projection. For way more details, see panda_pile::why, and this section for why I'm interested in explicitly working with futures rather than with async functions.

Related

What is the type for a vector of async functions that return "impl Responder"?

use actix_web::{delete, get, post, put, HttpResponse, Responder};
#[get("/user")]
async fn get_user() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
#[post("/user")]
async fn add_user() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
#[delete("/user")]
async fn delete_user() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
#[put("/user")]
async fn update_user() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
pub const my_functions: Vec<fn() -> impl Responder> = vec![get_user, add_user, delete_user, apdate_user].iter();
Trying to create web app with actix.rs. I want to split all API handlers to controllers and than map it as the services like App::new().service(func1).service(func2).
I can't understand how to add correct type for vector.
The type .body() returns is HttpResponse. But you cannot put your functions together in a vector, for two reasons: a) The underlying type of impl Trait is supposed to be opaque. The compiler won't let you use it, even if you know it, to not leak encapsulation. From the compiler point of view, you have different functions that returns different types. b) even if you would specify the type directly (and not rely on impl Trait), like #StefanZobel said they're async functions, and thus returns an impl Future<...>. The returned future is a different type for each function.
You can use a closure to wrap the futures into Pin<Box<dyn Future<...>>> (you can use dyn Responder too, or specify the concrete type. I wrote like if you specified the concrete type):
let my_functions: Vec<fn() -> Pin<Box<dyn Future<Output = HttpResponse>>>> = vec![|| Box::pin(get_user()), || Box::pin(add_user), || Box::pin(delete_user), || Box::pin(update_user)].iter();
Also note that you cannot create a Vec (nor a Box) inside const or static.
But all of that doesn't matter because you wrapped your functions with actix's macros (#[get("...")] etc.). They transform the function into an anonymous struct that implements HttpServiceFactory. So you can't just call them or whatever. What you need to do depends on what you want to do with your functions, but you can e.g. wrap them into Box<dyn HttpServiceFactory>

Rust Futures for String

I've been trying to understand and play with futures (version 0.3) but couldn't make this work. As I understand, a function is able to return a future of type A only if the type A implements the future trait. If I create a struct and implement the future trait, it's okay but why String doesn't work?
use futures::prelude::*;
async fn future_test() -> impl Future<Output=String> {
return "test".to_string();
}
I get the error:
the trait bound `std::string::String: core::future::future::Future` is not satisfied
the trait `core::future::future::Future` is not implemented for `std::string::String`
note: the return type of a function must have a statically known sizerustc(E0277)
So I told myself, okay then I can use Box like:
async fn future_test() -> impl Future<Output=Box<String>> {
return Box::new("test".to_string());
}
But the error is same:
the trait bound `std::string::String: core::future::future::Future` is not satisfied
the trait `core::future::future::Future` is not implemented for `std::string::String`
note: the return type of a function must have a statically known sizerustc(E0277)
What am I doing wrong? And why does the future hold the String instead of the Box itself?
When a function is declared async, it implicitly returns a future, with the return type of the function as its Output type. So you would write this function:
async fn future_test() -> String {
"test".to_string()
}
Alternatively, if you wanted to explicitly specify return type as a Future, you would drop the async keyword. If you did that you would also need to construct a future to return, and you would not be able to use await inside the function.
fn future_test2() -> impl Future<Output=String> {
ready("test2".to_string())
}
Note that futures::ready constructs a Future that is immediately ready, which is appropriate in this case since there is no actual asynchronous activity going on in this function.
Link to Playground

Rust - Wrapping FFI Pointers

I'm trying to wrap a FFI in a Rust Safe way.
The FFI Exposes raw pointers to structs with vtables, basically a struct looks like this:
pub struct InterfaceVTBL {
pub Release: unsafe extern "system" fn(This: *mut Interface) -> u64
}
pub struct Interface {
pub lpVtbl: *const InterfaceVTBL,
}
impl Interface {
pub unsafe fn Release(&self) -> u64 {
((*self.lpVtbl).Release)(self as *const _ as *mut _)
}
}
The Release Method is important, because it has to be called, when you are finished using the pointer to avoid a memory leak.
Now, im currently wrapping the pointers i get into Container Structs like this:
pub struct InterfaceContainer {
interface: *mut Interface
}
impl InterfaceContainer {
fn Release(&mut self) {
let reference = &*self.interface;
reference.Release();
}
}
impl Drop for InterfaceContainer {
fn drop(&mut self) {
self.Release();
}
}
Notice, that i didn't make the Release function of the Container pub, because it really should only be called on drop.
Now, the problem i'm facing, is that i need to pass the raw pointer to the interface to FFI Functions that will most likely be in different modules than the container structs, so they can't access the raw pointers in the Containers.
I could of course make the pointers pub or add a get_ptr function that returns a reference to the pointer, but i think that would defeat the purpose of wrapping the pointer in the first place, since all restrictions on function use through the pointers could be circumvented.
Now, im asking, is there a different way of exposing the pointer to those functions only, that i missed, or do i have to use an entirely different approach to wrapping those pointers?
Answers are much appreciated, thanks in advance.
Found a Solution:
Using pub (crate), the internal pointer can be made accessible only to code in the crate and not to outside users.

How to process a vector as an asynchronous stream?

In my RSS reader project, I want to read my RSS feeds asynchronously. Currently, they're read synchronously thanks to this code block
self.feeds = self
.feeds
.iter()
.map(|f| f.read(&self.settings))
.collect::<Vec<Feed>>();
I want to make that code asynchronous, because it will allow me to better handle poor web server responses.
I understand I can use a Stream that I can create from my Vec using stream::from_iter(...) which transforms the code into something like
self.feeds = stream::from_iter(self.feeds.iter())
.map(|f| f.read(&self.settings))
// ???
.collect::<Vec<Feed>>()
}
But then, I have two questions
How to have results joined into a Vec (which is a synchronous struct)?
How to execute that stream? I was thinking about using task::spawn but it doesn't seems to work ...
How to execute that stream? I was thinking about using task::spawn but it doesn't seems to work
In the async/await world, asynchronous code is meant to be executed by an executor, which is not part of the standard library but provided by third-party crates such as tokio. task::spawn only schedules one instance of async fn to run, not actually running it.
How to have results joined into a vec (which is a sync struct)
The bread and butter of your rss reader seems to be f.read. It should be turned into an asynchronous function. Then the vector of feeds will be mapped into a vector of futures, which need to be polled to completion.
The futures crate has futures::stream::futures_unordered::FuturesUnordered to help you do that. FuturesUnordered itself implements Stream trait. This stream is then collected into the result vector and awaited to completion like so:
//# tokio = { version = "0.2.4", features = ["full"] }
//# futures = "0.3.1"
use tokio::time::delay_for;
use futures::stream::StreamExt;
use futures::stream::futures_unordered::FuturesUnordered;
use std::error::Error;
use std::time::{Duration, Instant};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let start = Instant::now();
let feeds = (0..10).collect::<Vec<_>>();
let res = read_feeds(feeds).await;
dbg!(res);
dbg!(start.elapsed());
Ok(())
}
async fn read_feeds(feeds: Vec<u32>) -> Vec<u32> {
feeds.iter()
.map(read_feed)
.collect::<FuturesUnordered<_>>()
.collect::<Vec<_>>()
.await
}
async fn read_feed(feed: &u32) -> u32 {
delay_for(Duration::from_millis(500)).await;
feed * 2
}
delay_for is to simulate the potentially expensive operation. It also helps to demonstrate that these readings indeed happen concurrently without any explicit thread related logic.
One nuance here. Unlike its synchronous counterpart, the results of reading rss feeds aren't in the same order of feeds themselves any more, whichever returns the first will be at the front. You need to deal with that somehow.

static struct with raw pointer gives "`core::marker::Sync` is not implemented..."

I am trying to create some static data structures in Rust that will be passed to C code. Below is a minimal example that fails to compile, and I have no idea what the error means in this context. So the question is, why is it failing and how do I fix it?
pub struct MyStruct {
pub name: *const str,
}
static mystruct: MyStruct = MyStruct {name: "why!!!\0"};
// src/lib.rs:52:29: 52:56 error: the trait `core::marker::Sync` is not implemented for the type `*const str`
// src/lib.rs:52 static mystruct: MyStruct = MyStruct {name: "why!!!\0"};
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~
Here, Sync means "can be safely shared between tasks when aliased". Rust considers types that contain raw pointers to not be shareable between threads by default, and a static variable needs to be shareable.
If you have reasons to believe that your type is indeed shareable between threads with no problem, then you can assert to the compiler that you know better:
unsafe impl Sync for MyStruct { }
If you have control over the C library however, I would encourage lifting the requirement that the struct needs to be static - maybe designing the library around a handle of some sort.

Resources