How do I most idiomatically write an async IO library in Rust for no_std platforms? - io

I'm building a library to be used on a no_std platform which allows you to do some common network-related IO, such as making HTTP requests or reading from/writing to Websockets.
Now, I would like this library to be a well-behaved citizen so that it can be easily included in other no_std applications. I hence want to package the library by implementing reasonable traits etc. The library would allow me to not have to use alloc, so supporting non-alloc no_std would be ideal.
These are the options I have looked at:
embedded_hal and nb: These crates are really low level (no generic traits like Read and Write or anything higher level) and the async model doesn't seem to be compatible with async/await
genio/core_io/...: These don't support async IO at all.
embrio: Seems interesting but it seems like using it would tie me to one specific environment, making the library less portable.
tokio v0.2.x: I would love to use it but there is no no_std support at all.
futures::io v0.3.x: Again, would love to use it but there is no no_std support.
Which async IO abstraction should I use in a no_std environment? If there is no good option right now, which one should I bet on/help out with for the future?

Take a look a look at embassy-rs. There is a very active community. Currently, embassy-rs supports;
Hardware abstraction layers
Time
Networking
Bluetooth
Lora
USB
DFU
All built on rust async. There are also some really nice macros to generate static buffers for tasks, so you don't need alloc.

Related

Why are asynchronous runtimes like Tokio necessary?

My first experience doing a computer system project was building a server using vanilla Java and then a client on an Android phone. Since then, I've found that there are a lot of frameworks to help manage scalability and remove the need to write boilerplate code.
I'm trying to understand what services like Tokio and Rayon enable.
I came across this paragraph on the Tokio tutorial page and I'm having a hard time understanding it
When you write your application in an asynchronous manner, you enable it to scale much better by reducing the cost of doing many things at the same time. However, asynchronous Rust code does not run on its own, so you must choose a runtime to execute it.
I first thought a "runtime" might refer to where the binary can run, but it looks like Tokio just provides functions that are already available in the Rust standard library while Rayon implements functions that aren't in the standard library.
Are the standard implementations for asynchronous functions written poorly in the standard library or am I not understanding what service Tokio is providing?
Rust currently does not provide an async runtime in the standard library. For full details, see Asynchronous Programming in Rust, and particularly the chapter on "The Async Ecosystem."
Rust currently provides only the bare essentials for writing async code. Importantly, executors, tasks, reactors, combinators, and low-level I/O futures and traits are not yet provided in the standard library. In the meantime, community-provided async ecosystems fill in these gaps.
Rust has very strict backward compatibility requirements, and they haven't chosen to lock-in a specific runtime. There are reasons to pick one over another (features versus size for example), and making it part of the standard library would impose certain choices that aren't clearly the right ones for all projects. This may change in the future as the community projects better explore this space and help determine the best mix of choices without the strong backward compatibility promises.

How do I write an async method with Tokio?

I'm trying to write a library that will connect to remote servers and exchange data. I did this in C++ using Boost::Asio and am trying to do the same with Rust.
One of the problems I have is mapping concepts from Asio, like async_write/read to Tokio, starting with the fact that seemingly all Tokio examples demand that I replace my main() with an async main(), while I would like to encapsulate all my async code in structures and associated implementations.
Is it possible to use Tokio without replacing main()? Is mio perhaps the only way?
You can create a runtime manually using Runtime::new() which is what the tokio main macro is doing under the hood. It's just for an awful lot of apps, especially examples that's just boilerplate. So the macro automates the simple case.
However, depending on the context of your library, it may be more idiomatic to provide a future based API, and then leave the app consumer to set up the runtime.

How can we use Haskell with OSRM libraries?

We want to use libOSRM for routing. Currently we are calling its http services. For better performance, I want to call its dynamic library. When reading Haskell FFI, I guess I can compile and links its source (instead of compiled dynamic library) with my Haskell code.
1. Which method is better?
2. How can I do each alternative?
Note that OSRM is full of structs that I am not sure how to import into haskell. c2hsc does not install (cabal raises error!). I do not know how to link the whole source of OSRM, from the other hand.
I prototyped some Haskell bindings going through an API and ABI compatible C wrapper: libosrmc.
Feel free to give it a try and send in pull requests. It's exposing just a small part of the API and is based on OSRM version 5.4; you might need to invest some time. But the overall architecture and ideas still apply. Here are the Haskell bindings.
I recommend thinking twice about going the libosrm/FFI way with Haskell instead of sending HTTP requests: benchmark up-front if it's worth the troubles.
you can look at https://github.com/daniel-j-h/hosrm-qa The project is PoC-only and uses HTTP OSRM API instead of Haskell FFI.

Options for wrapping a C++ library for Haskell (and other languages)

This question is about design / is fairly open-ended.
I'd like to use OpenCV, a large C++ library, from Haskell.
The closest solution at the moment is probably Arjun Comar's attempt to adapt the Python / Java binding generator.
See here, here, and here.
His approach generates a C interface, which is then wrapped using hsc2hs.
Due to OpenCV's lack of referential transparency in its API, as well as its frequent use of call parameters for output, for Arjun's approach to fully succeed he'll need to define a new API for OpenCV, and implement it in terms of the existing one.
So, it seems it might not be too much extra work to go whole-hog and define an API using an interface description languages (IDL), such as SWIG, protobuf-with-RPC, or Apache Thrift.
This would provide interfaces to a number of languages besides Haskell.
My questions:
Is there anything better than SWIG for a server-free solution?
(I just want to call into C++; I'd rather not go through a local server.)
If there's no good server-free solution, should I use protobuf-with-RPC or Thrift?
Related: How good is Thrift's Haskell support?
From the code, it looks like it needs updating (I see references to GHC 6).
Related: What's a good protobuf-with-RPC solution?
With Apache Thrift, you get Haskell support. You are correct, code is not generally "latest", but you rarely care. You can do complex things on other abstraction levels and keep things as simple as possible at messaging level.
Google Protobuf has no support for Haskell, nor does SWIG. With Protobuf you get C++, Java, JavaScript and Python, to my knowledge the main languages at Google. Have a look at this presentation. Without contest, Thrift and Protobuf are the best in house.
It seems in your case you have to go with Thrift, as it supports Haskell.
It sounds like the foreign function interface for C++ is what you want:
Hackage,
Github
Disclaimer: I haven't used it, only heard good things about it.

Safe execution of untrusted Haskell code

I'm looking for a way to run an arbitrary Haskell code safely (or refuse to run unsafe code).
Must have:
module/function whitelist
timeout on execution
memory usage restriction
Capabilities I would like to see:
ability to kill thread
compiling the modules to native code
caching of compiled code
running several interpreters concurrently
complex datatype for compiler errors (insted of simple message in String)
With that sort of functionality it would be possible to implement a browser plugin capable of running arbitrary Haskell code, which is the idea I have in mind.
EDIT: I've got two answers, both great. Thanks! The sad part is that there doesn't seem to be ready-to-go library, just a similar program. It's a useful resource though. Anyway I think I'll wait for 7.2.1 to be released and try to use SafeHaskell in my own program.
We've been doing this for about 8 years now in lambdabot, which supports:
a controlled namespace
OS-enforced timeouts
native code modules
caching
concurrent interactive top-levels
custom error message returns.
This series of rules is documented, see:
Safely running untrusted Haskell code
mueval, an alternative implementation based on ghc-api
The approach to safety taken in lambdabot inspired the Safe Haskell language extension work.
For approaches to dynamic extension of compiled Haskell applications, in Haskell, see the two papers:
Dynamic Extension of Typed Functional Languages, and
Dynamic applications from the ground up.
GHC 7.2.1 will likely have a new facility called SafeHaskell which covers some of what you want. SafeHaskell ensures type-safety (so things like unsafePerformIO are outlawed), and establishes a trust mechanism, so that a library with a safe API but implemented using unsafe features can be trusted. It is designed exactly for running untrusted code.
For the other practical aspects (timeouts and so on), lambdabot as Don says would be a great place to look.

Resources