Skip to main content

Crate uiharu

Crate uiharu 

Source
Expand description

§uiharu

A streaming protocol decode engine for logic analyzer software, automated tests and waveform tools. Written in Rust and licensed under Apache-2.0.

Decoders process blocks of logic samples, exchange typed events through bounded queues with backpressure, and compose into a checked decode graph. Events within each output stream are independent of block boundaries and reader pauses.

cargo add uiharu

Using a published crate requires Rust 1.90 or newer. Node/pnpm is needed only to develop the TypeScript decoders in a source checkout; published packages already contain the generated Rust.

§A typed SPI pipeline

use std::sync::Arc;
use uiharu::{Graph, SignalItem, SourceSpec, TimeBase};
use uiharu::protocols::spi::{Spi, SpiConfig};

let mut graph = Graph::new();
let source = graph.source(SourceSpec::new("logic", 4, TimeBase::new(25_000_000)))?;
let spi = graph.add(Spi::new(SpiConfig::default())?);
graph.connect(source.samples, Spi::input(spi))?;
let output = graph.expose("spi", Spi::events(spi))?;
let mut pipeline = graph.build()?;
let events = pipeline.exposed(output).expect("exposed once");

// For each bit-packed LogicBlock supplied by your capture source:
pipeline.push(source.id, SignalItem::Data(Arc::new(block)))?;
pipeline.run();
while let Some(item) = events.next() {
    // Typed SPI events, gaps, progress and end-of-stream notifications.
    println!("{item:?}");
    if matches!(item, uiharu::Item::End(_)) {
        break;
    }
}

The complete SPI example generates and decodes a transaction. Add another decoder to consume the SPI events, for example SPI NOR flash, SD cards or an nRF24L01+ radio.

§Features

FeatureDefaultProvides
protocolsYesBuilt-in decoders under uiharu::protocols
registryNoNamed decoders, UI metadata, JSON pipeline descriptions and runtime IR loading under uiharu::registry
testingNoDecoder acceptance harnesses under uiharu::testing, intended for dev-dependencies

With default-features = false, only the core runtime is included. For a configurable application, run cargo add uiharu --features registry.

§Command line

cargo install uiharu-cli --locked
uiharu gen flash.bin
uiharu decode flash.bin --stats

§Documentation and compatibility

The uiharu-* crates share a release version independent of the HSync application. Before 1.0, a minor version may introduce incompatible API changes; patch releases preserve API compatibility. IR format compatibility is identified separately by the module’s ir field and uiharu_ir::IR_VERSION.

Re-exports§

pub use uiharu_protocols as protocols;
pub use uiharu_registry as registry;

Modules§

dsl
The runtime of decoders compiled from the DSL: what the backend emits generated code against (docs/dsl.md §3 and §5).
exec
Running a built graph: feeding sources, polling the nodes until nothing can move, and reading the exposed outputs.
graph
Building a decode graph: sources of logic samples, decoder nodes, the connections between their typed ports and the outputs exposed to the caller. Connecting checks that the ports agree on the schema and that the input’s requirements are met; building checks that every input is connected, that the graph has no cycle and that each node reads one time domain.
hex_u64
Integers wider than JSON readers keep exactly.
node
Decoders as the executor runs them: a node declares its ports, is started with its ports bound to queues, and runs as one future that reads through an Inbox or a SignalCursor and writes through an Outbox.
schema
What ports carry and what they require of each other: the identity of an event schema, the properties an output declares (word width, bit order, which lines are present …) and the requirements an input places on them. The graph checks them when ports are connected.
signal
Logic samples as decoders read them: blocks of bit-packed samples, and the cursor that walks a stream of blocks looking for edges and reading levels.
stream
Event streams: the envelope every event carries, the control items that travel with events, and the bounded broadcast queue that hands one producer’s items to every reader.
testing
Helpers for testing decoders: a one-source pipeline driven block by block, with the blocks cut to chosen sizes, gaps announced and the reader pausing between blocks, and the check the acceptance criteria call for — that none of this changes the events.
time
Time as decoders see it: ticks on a source’s sample clock, tick ranges and the time base that turns them into seconds. Decoders never work in seconds; everything they emit is placed in ticks so that results stay exact and comparable.

Structs§

Broadcast
A bounded queue from one producer to any number of readers.
ChannelMask
A set of channels: bit i stands for channel i.
DynExposedRef
An output exposed through Graph::expose_dyn, read with Pipeline::exposed_dyn.
DynInput
An input port named at run time; see Graph::input.
DynOutput
An output port named at run time, for graphs built from a description rather than from typed code; see Graph::output and Graph::connect_dyn.
Event
An event with its envelope: where on the signal it comes from, when it became certain and its position in the stream.
Exposed
The caller’s reader on an exposed output.
ExposedRef
An exposed output, read through Pipeline::exposed.
Graph
A decode graph under construction.
GraphConfig
Limits every node and queue of a graph shares.
Inbox
A node’s reader on one of its input queues.
InputRef
An input port reading T events.
InputSpec
An input port as a node declares it.
Io
The queues bound to a node’s ports, handed to Node::start, with what the node may need to know about them: the time base its inputs are on and the properties of the outputs they read.
Levels
The levels of every channel at one tick: bit i set means channel i is high.
LogicBlock
A block of samples: len ticks from start on channels channels, bit-packed per channel, least significant bit first.
LogicBlockBuilder
Builds a LogicBlock sample by sample.
NodeCx
The executor’s side of a node: its budget, why it last paused and how much it has done.
NodeId
A node in a graph.
NodeSpec
Outbox
A node’s writer on one of its output queues.
OutputRef
An output port carrying T events, as Graph::connect and Graph::expose take it.
OutputSpec
An output port as a node declares it.
Pipeline
A built graph, ready to take samples and run.
ProgressSink
An output seen only as a place to pass progress on, for cursors over a contract. A cursor passes the progress it meets inside a frame on through it, held back to what the decoder has read through the cursor and not reported yet: what it consumed since it last took the provenance (consumed()), and what it says it still holds (ProgressSink::hold) when it took provenance early for an event still to come. Made by Outbox::progress_sink; clones share their state.
Props
The properties of an output port, by name.
Provenance
Where an event comes from: the ticks it covers and when it became certain.
QueueStat
The state of one queue.
ReaderId
A reader’s identity on a Broadcast.
Requires
The requirements of an input port, by property name.
RunReport
What one run of the pipeline did.
SchemaId
The name and version of an event schema, such as spi.events version 1. Two ports are compatible only when both agree.
SignalCursor
A decoder’s view of a source: a position in its samples, with the levels just before it.
SourceHandle
The source as added to a graph: its id and its output.
SourceId
A source of logic samples in a graph.
SourceSpec
A source of logic samples, as Graph::source takes it.
Stats
The state of every queue of a pipeline.
Tick
A sample index on a source’s clock, counted from the first sample the source produced.
TickRange
A half-open range of ticks, start..end. Serialized as the pair [start, end].
TimeBase
The clock of a source: how many ticks make a second.

Enums§

BlockError
Why samples do not make a block.
Change
What a wait for an edge finds.
GraphError
Why a graph cannot be built as asked.
Item
What travels along a stream: events, and the control items that frame them.
PropValue
A property of an output port.
PushError
Why a source did not take an item.
Requirement
What an input requires of one property of the output it is connected to.
Sample
What reading the levels at the cursor finds.
SignalItem
What a source feeds into a pipeline.
Wait
What a node is waiting for when its future returns Pending.

Constants§

LOGIC_SAMPLES
The schema of a source’s output: blocks of logic samples.
MAX_CHANNELS
The most channels a source may have.

Traits§

EventSchema
The payload type of an event stream, tied to its schema.
Node
A decoder, or any other step of a decode graph.
Readable
An input a node can wait on: an inbox, or a signal cursor.

Functions§

ready_all
Waits until every input in inputs has something to read. A node with several inputs waits on all of them, then takes the item whose time (Item::time) is earliest — the one with the lowest index on a tie — so that what it does depends on the items alone, never on which input happened to fill first.

Type Aliases§

NodeFuture
The future that runs a node.