Rust getting started

Build your first temporal comparison in Rust.

Start from an empty Cargo binary. The complete example uses Rust-native types and explicit error propagation to compare two providers' offline windows.

1. Create the project

Install Spanfold from crates.io.

cargo new spanfold-quickstart
cd spanfold-quickstart
cargo add spanfold@0.1.1

2. Add the example

Replace src/main.rs.

Processing positions keep the first result easy to inspect: each ingested event advances the position by one.

use spanfold::for_events;
use std::error::Error;

#[derive(Clone)]
struct DeviceStatus {
    device_id: String,
    is_online: bool,
}

fn main() -> Result<(), Box<dyn Error>> {
    let mut pipeline = for_events::<DeviceStatus>()
        .record_windows()
        .track_window(
            "DeviceOffline",
            |status| status.device_id.clone(),
            |status| !status.is_online,
        )
        .build()?;

    pipeline.ingest(status(true), Some("provider-a"), None)?;  // position 1
    pipeline.ingest(status(true), Some("provider-b"), None)?;  // position 2
    pipeline.ingest(status(false), Some("provider-a"), None)?; // position 3, A opens
    pipeline.ingest(status(false), Some("provider-b"), None)?; // position 4, B opens
    pipeline.ingest(status(true), Some("provider-b"), None)?;  // position 5, B closes
    pipeline.ingest(status(true), Some("provider-a"), None)?;  // position 6, A closes

    let result = pipeline
        .history()
        .compare("Provider comparison")
        .target_source("provider-a")
        .against_source("provider-b")
        .scope_window("DeviceOffline")
        .overlap()
        .residual()
        .missing()
        .run();

    println!("closed windows: {}", pipeline.history().closed_windows().len());
    println!("overlap rows: {}", result.overlap_rows.len());
    println!("provider-a-only rows: {}", result.residual_rows.len());
    println!("provider-b-only rows: {}", result.missing_rows.len());

    for row in result.overlap_rows.iter() {
        println!("overlap {}: {}..{}", row.key, row.range.start, row.range.end);
    }

    for row in result.residual_rows.iter() {
        println!("a-only {}: {}..{}", row.key, row.range.start, row.range.end);
    }

    Ok(())
}

fn status(is_online: bool) -> DeviceStatus {
    DeviceStatus {
        device_id: "device-17".into(),
        is_online,
    }
}

3. Run it

Inspect the comparison rows.

cargo run
closed windows: 2
overlap rows: 1
provider-a-only rows: 2
provider-b-only rows: 0
overlap device-17: 4..5
a-only device-17: 3..4
a-only device-17: 5..6

Provider A was offline from position 3 to 6; provider B from 4 to 5. The result keeps the shared interval and both A-only intervals as separate rows.

4. Continue

Move from the first comparison to your own history.