transformable_channels 0.1.1

Rust channels are a convenient abstraction, but for many uses cases, they miss high-level transformations such as `map`, `filter`, ... . This crate introduces them.
Documentation
  • Coverage
  • 93.75%
    15 out of 16 items documented5 out of 14 items with examples
  • Size
  • Source code size: 19.9 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 3.95 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 9s Average build duration of successful builds.
  • all releases: 9s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • Documentation
  • Yoric/channels.rs
    4 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • Yoric

Build Status

Documentation

The problem at hand

Consider an event loop, defined as follows:

let (tx, rx) = channel();
thread::spawn(move || {
  for event in rx {
    match event {
      UIEvent::KeyboardEvent(ev) => { ... },
      UIEvent::MouseEvent(ev) => { ... },
      ...
    }
  }
});

Now, imagine a system library that can watch for keyboard events, with the following signature:

impl ThirdPartyLibrary {
  fn register_watch(&self, on_event: Sender<PrimitiveKeyboardEvent>) -> ...;
}

How can we interact with this library? Well, with Sender, the only way is to fire another thread, as follows:

let (tx2, rx2) = channel();
let tx = tx.clone(); // That's the tx for my event loop, see above.
thread::spawn(move || {
  for ev in rx {
    match tx.send(UIEvent::KeyboardEvent(ev) {
      Ok(_) => {},
      Err(_) => return, // Cleanup if nobody is listening anymore.
    }
  }
});

third_party_library.register_watch(tx2);

Wouldn't it be nicer and more resource-efficient if we could write the following and have it work without spawning a thread?

third_party_library.register_watch(tx.map(|ev| UIEvent::KeyboardEvent(ev)));

Now, let's assume that the situation is slightly more complicated and that our system needs to handle several keyboards. Now, we need to label each keyboard with a unique key.

With Sender, the only solution is to fire one thread per keyboard, i.e.

let key = ...;
let (tx3, rx3) = channel();
let tx = tx.clone(); // That's the tx for my event loop, see above.
thread::spawn(move || {
  for ev in rx {
    match tx.send(UIEvent::KeyboardEvent(key, ev) {
      Ok(_) => {},
      Err(_) => return, // Cleanup if nobody is listening anymore.
    }
  }
});

third_party_library.register_watch(tx3);

Wouldn't it be nicer and more resource-efficient if we could write the following and have it work without spawning a thread?

let key = ...;
third_party_library.register_watch(tx.map(move |ev| UIEvent::KeyboardEvent(key, ev)));

This crate is designed to make the nicer and more resource-efficient strategy possible.