Closed Bug 1868369 Opened 2 years ago Closed 2 years ago

Implement a Rust translation layer between XPCOM's asynchronous operations and Rust's async features

Categories

(MailNews Core :: General, enhancement, P1)

enhancement

Tracking

(Not tracked)

RESOLVED FIXED
124 Branch

People

(Reporter: babolivier, Assigned: babolivier)

References

(Blocks 2 open bugs)

Details

Attachments

(1 file)

We want to plug general-purpose Rust code into Thunderbird in a way that allows such code to run asynchronous operations (e.g. nsIChannel::AsyncOpen) without having to implement XPCOM interfaces itself. To start with, we want to implement an interface layer that wraps an XPCOM async call into something that implements Rust's Future trait.

Assignee: nobody → brendan
Severity: -- → N/A
Status: NEW → ASSIGNED
Type: task → enhancement
Priority: -- → P1
Blocks: 1868370

I've been through a few iterations of this one. Most importantly, I need the
underlying nsIStreamListener to implement some off-interfaces methods so the
Future it's wrapped into can query its status, give it a way to signal when
the request has finished, read from its buffer etc.

Ideally I also want the crate to work with any custom nsIStreamListener to
allow for maximum flexibility, so I tried a few approaches based on traits.
Ultimately this ended up not working, due to complications of keeping a
reference to traits that aren't object-safe (namely XpCom). With more fiddling
I might have been able to get it working, but that would likely have required a
whole lot more abstraction between this crate and the XPCOM bindings. It will
probably be worth exploring a refactoring of this crate once we have friendlier
XPCOM bindings.

I fell back onto being more strict about the listener used in the asynchronous
operation, by having it be defined as a struct rather than a trait, and have its
only function be buffering the incoming data. Which, one could argue is also
more idiomatic to Rust - futures aren't supposed to be working until they're
poll()ed.

It's worth noting that we make an exception to the rule of not working between
poll()s with regards to buffering from the stream. This is because the call
contract for OnDataAvailable is that the stream cannot be interacted with
once the call has finished, and since we're dealing with asynchronous code
running on the same thread, there's no real way to block the call until the next
poll() (at least not without going deeper into the async layers by wrapping
yet another future into the stream listener, which I think would add a great
deal of complexity). In practice this seems to be fine.

Blocks: 1869277
Attachment #9367149 - Attachment description: WIP: Bug 1868369 - Add a Rust crate to wrap nsIChannel::AsyncOpen into a Future. → Bug 1868369 - Add a Rust crate to wrap nsIChannel::AsyncOpen into a Future. r=leftmostcat
Target Milestone: --- → 124 Branch

Pushed by geoff@darktrojan.net:
https://hg.mozilla.org/comm-central/rev/5caaab0fbde5
Add a Rust crate to wrap nsIChannel::AsyncOpen into a Future. r=leftmostcat

Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: