Skip to main content

Imitator

Struct Imitator 

Source
pub struct Imitator<T: 'static> { /* private fields */ }
Expand description

Imitators are used to create cyclic streams. Created by Stream::imitator().

§Anatomy of an FRP app

cycle.js taught me one one way to structure an app built on FRP. A key ingredient are “cyclic streams”.

  • A driver is something isolating communcation to the rest of thew world. This could be requests against an API, database or a UI.
  • Drivers are two-way communications.
  • An app is a main function that have driver input as argument and driver output as return value.
  • App input is called sources.
  • App output is called sinks.

These components would be in different files, but here’s a distilled example:

use xi::{Stream, Sink};

enum DriverIn {
  // ... event type of input _from_ the driver.
}
#[derive(Clone)] // needed for imitate
enum DriverOut {
  // ... event type of output _to_ the driver.
}

// The driver, which also is a function.
fn my_driver(out: Stream<DriverOut>) -> Stream<DriverIn> {
    let sink = Stream::sink();

    // React to input from `out` and
    // produce output into `sink`.

    sink.stream()
}

// Input to the app_main from the drivers
struct AppSources {
    my_driver: Stream<DriverIn>,
}

// Output from the app_main to the drivers
struct AppSinks {
    my_driver: Stream<DriverOut>,
}

// The main function of the app
fn app_main(sources: AppSources) -> AppSinks {

    // React to input from the sources, and derive
    // output to the sinks. Produce an "app state".

    // This is just to make it compile. The output
    // would be derived from the app state.
    let my_driver_out = Stream::never();

    return AppSinks {
        my_driver: my_driver_out,
    }
}

// This function does what "cycle.js run" does (but in
// javascript it can be dynamic).
fn run() {
    // imitator to cycle back output from main
    let driver_out = Stream::imitator();

    // connect driver
    let driver_in = my_driver(driver_out.stream());

    // create sources for app main function
    let app_sources = AppSources {
        my_driver: driver_in,
    };

    // run main function
    let app_sinks = app_main(app_sources);

    // cycle back output to driver
    driver_out.imitate(&app_sinks.my_driver);
}

Implementations§

Source§

impl<T: Clone> Imitator<T>

Source

pub fn imitate(self, other: &Stream<T>) -> Subscription

Start imitating another stream. This consumes the imitator since it can only imitate one other stream.

Source

pub fn stream(&self) -> Stream<T>

Get a stream of events from this imitator. One stream instance is created for each call, and they all receive the events from the imitated stream.

let imitator = xi::Stream::imitator();

let coll1 = imitator.stream().collect();
let coll2 = imitator.stream().collect();

let sink = xi::Stream::sink();
let stream = sink.stream();

imitator.imitate(&stream);

sink.update(42);
sink.end(); // imitator also ends here

assert_eq!(coll1.wait(), vec![42]);
assert_eq!(coll2.wait(), vec![42]);

Auto Trait Implementations§

§

impl<T> Freeze for Imitator<T>

§

impl<T> RefUnwindSafe for Imitator<T>

§

impl<T> Send for Imitator<T>
where T: Send,

§

impl<T> Sync for Imitator<T>
where T: Send,

§

impl<T> Unpin for Imitator<T>

§

impl<T> UnsafeUnpin for Imitator<T>

§

impl<T> UnwindSafe for Imitator<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.