-
Notifications
You must be signed in to change notification settings - Fork 636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Compat blog post #1226
WIP: Compat blog post #1226
Conversation
Alright. Now it's done. Plz review Note: I plan to turn various code snippets into links once we've released the docs for alpha.4. The docs for alpha.3 don't include the compatibility layer (an oversight ^^'). |
The compatibility layer can be enabled by setting the `compat` feature your `Cargo.toml`: | ||
|
||
```toml | ||
futures-preview = { version = "0.3.0-alpha.3", features = ["compat"] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably also include the "tokio-compat"
feature, otherwise the two examples won't run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
futures-preview = { version = "0.3.0-alpha.3", features = ["compat"] } | ||
``` | ||
|
||
To use `futures@0.1` and `futures@0.3` together in a single project, we can make use of the new cargo feature for renaming dependencies. Why? Because, even though the `futures@0.3` crate is called `futures-preview` on crates.io, it's lib name is also `futures`. By renaming `futures` version 0.1 to `futures01`, we can avoid a name colision: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
colision
=> collision
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
# Futures 0.1 Compatibility Layer | ||
|
||
Rust's futures ecosystem is currenlty split in two: On the one hand we have the vibrant ecosystem built around `futures@0.1` with its many libraries working on stable Rust and on the other hand there's the unstable `futures@0.3` ecosystem with support for the ergonomic and powerful `async`/`await` language feature. To bridge the gap between these two worlds we've introduced with `0.3.0-alpha.3` a compatibility layer that makes it possible to use `futures@0.1` and `futures@0.3` futures and streams together in one project. This blog post aims to give an overview over how to use it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we've introduced with
0.3.1-alpha.3
a compatibility layer
reads weirdly on first glance, maybe something like
To bridge the gap between these two worlds we have introduced a compatibility layer (first released as part of
futures 0.3.0-alpha.3
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
let future03 = future01.compat(); | ||
``` | ||
|
||
It converts a 0.1 `Future<Item = T, Error = E>` into a 0.3 `Future<Output = Result<T, E>>`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a note that even with this it's not possible to run a tokio based future on a 0.3 executor because there is no reactor available? (I have an idea for another combinator that would allow this, but haven't gotten round to trying it out yet).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't aware of this limitation. I'm not sure how to phrase this. Could you maybe formulate how to explain this best?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try and throw together a short failing example, I think that might be the best way to show why it doesn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, damn, it's not even just that there's no reactor available, the current compat01to03
implementation won't work on any futures(0.3)
executor because there's no thread-local Task
to store the Notify
in:
#![feature(async_await, await_macro, futures_api)]
use std::net::ToSocketAddrs;
use futures::compat::Future01CompatExt;
const MSG: &[u8] = &[0x44, 0x01, 0x6d, 0xb3, 0xb3, 0xb1, 0x28, 0xba, 0xb4, 0x74, 0x65, 0x73, 0x74];
async fn do_request() {
let addr = ("coap.me", 5683).to_socket_addrs().unwrap().next().unwrap();
let bind_addr = "0.0.0.0:0".parse().unwrap();
let socket = tokio::net::UdpSocket::bind(&bind_addr).unwrap();
let (socket, _) = await!(socket.send_dgram(MSG, &addr).compat()).unwrap();
let buffer = vec![0; 256];
let (_, buffer, length, _) = await!(socket.recv_dgram(buffer).compat()).unwrap();
let result = String::from_utf8_lossy(&buffer[..length]);
assert!(result.contains("welcome to the ETSI plugtest"))
}
fn main() {
futures::executor::block_on(do_request())
}
gives an error:
thread 'main' panicked at 'no Task is currently running', libcore/option.rs:1000:5
stack backtrace:
[...]
9: <futures::task_impl::NotifyHandle as core::clone::Clone>::clone
at /Users/travis/build/rust-lang/rust/src/libcore/option.rs:312
10: futures::task_impl::with
at /Users/Nemo157/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/task_impl/mod.rs:43
11: futures::task_impl::with_notify
at /Users/Nemo157/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.23/src/task_impl/mod.rs:471
12: futures_util::compat::compat01to03::<impl core::future::future::Future for futures_util::compat::compat::Compat<Fut, ()>>::poll
at /Users/Nemo157/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.3/src/compat/compat01to03.rs:21
[...]
26: futures_executor::local_pool::block_on
at /Users/Nemo157/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-executor-preview-0.3.0-alpha.3/src/local_pool.rs:224
[...]
The conversion from a 0.1 future to a 0.3 future also works via a `compat` combinator method: | ||
|
||
```rust | ||
use futures::compat::Futures01CompatExt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be use futures::compat::Future01CompatExt;
@carllerche This blog post talks about compatibility between 0.1 and 0.3 futures in general, but also about Tokio compatibility. Now, that I think it'd be best to place the general 0.1 <-> 0.3 compatibility layer in I'd love to hear your take on this. Would you be open for collaboration? |
I don't really have many thoughts as to what collaboration would look like. I have not dug into the compat layer in the futures lib. General thoughts:
Also, Last, keeping what I need in |
I'm going to continue writing this tomorrow if I find the time. In the meantime, here's what I have so far 🙂