futures-rs icon indicating copy to clipboard operation
futures-rs copied to clipboard

no_std support for futures-io

Open Nemo157 opened this issue 6 years ago • 6 comments

Inspired by @Ericson2314's comment on a portability-wg issue about allocation-less std::io::Error I decided to attempt a two-layered approach to Async{Read,Write} allowing supporting no_std targets with most of the futures-io and futures-util::io adaptors.

The main change required is a second set of traits (CoreAsync{Read,Write}) which have an associated error type instead of using std::io::Error, the Async{Read,Write} traits are then implemented on top of these traits where CoreAsync{Read,Write}::Error: Into<std::io::Error>.

One difficulty is that some of the more important adaptors (e.g. futures-util::io::ReadExact) re-use error variants from std::io::Error, my first attempt at working around this limitation is to force the underlying error type to provide at least the two variants that the adaptors require. This seems a bit messy, I'm unsure if there's a much nicer solution to this.

My main goal with this was to be able to use these adaptors with types from the embedded-hal library for non-blocking serial connections, via the nb library. I have an example of this compiling now, but I'll have to wait till I'm at work tomorrow to try and get it running on real hardware.

Links to the changes:


I'm creating this issue now to get feedback on whether this is something that might be supported by the core futures library at some point. I really would like to avoid splitting the ecosystem between std and no_std Futures, e.g. I'm likely to be looking at using/building a non-blocking CoAP library, and am hoping to be able to make it work with both std and no_std environments without much effort in the library itself.

Nemo157 avatar Mar 11 '18 13:03 Nemo157

And finally got round to using this on some real hardware, it works perfectly (although, integrating task notification into HAL layers without impacting non-futures use of them is stil an issue).

Nemo157 avatar Mar 19 '18 15:03 Nemo157

Thanks @Nemo157 for taking on this work! I strongly agree with your overall goals.

I'd really like to see if we can somehow finagle io::Error to work in core as a general solution to this problem. I will push on that with the libs team.

aturon avatar Mar 19 '18 22:03 aturon

Is there any blockers on this? I really wish there is some Read/Write traits accepted by the ecosystem (especially async). Otherwise most of the no_std bail out to core::fmt::Write, which is limited by str constrains or make their own traits.

Also since 0.3 picks up some nightly features (pin and arbitrary_self_types) maybe we should also use associated_type_defaults instead of supertrait approach, making default error type std::io::Error if std feature enabled, so that we don't introduce 2 traits for the same thing, making documentation and implementation on top of this traits much cleaner.

Object905 avatar Jun 01 '18 07:06 Object905

It would be really awesome if you could somehow write your embedded code as async functions, and then have some clever executor setup the necessary interrupts and call wfi when there's nothing to do. You could possibly end up with code as good (for power usage) as hand-written but with all the embedded details abstracted. Would be very cool.

derekdreery avatar Jul 06 '19 20:07 derekdreery

I don't believe this is something we'll be able to tackle without support from upstream, since I think it's important that these traits mirror the upstream std::io::Read/Write counterparts. I'm open to suggestions here, though, if anyone has ideas about how to avoid this restriction!

cramertj avatar Nov 01 '19 22:11 cramertj

@cramertj Not everything can be implemented for no_std for io, but most of it can now thanks to https://github.com/jethrogb/rust-core_io.

ghost avatar Jul 27 '20 12:07 ghost