Expand description
§osc7501-parser
Read status reports and terminal capability replies from
OSC 7501, revision 0.4.
Works without std or an allocator.
§Parse a report
[dependencies]
osc7501-parser = "0.1"use osc7501_parser::{Event, MAX_MESSAGE, parse_sequence};
fn main() -> Result<(), osc7501_parser::Error> {
let input = b"\x1b]7501;state=done:app=cargo:msg=T0s=\x1b\\";
if let Some(Event::Report(report)) = parse_sequence(input)? {
let mut storage = [0_u8; MAX_MESSAGE];
if let Some(message) = report.message() {
assert_eq!(message.decode_into(&mut storage)?, "OK");
}
}
Ok(())
}§Choose a parser
| You have | Use |
|---|---|
| A complete OSC sequence ending in BEL or ESC-backslash | parse_sequence |
| A body from your terminal’s escape-sequence handler | parse_body |
| OSC scanning across reads | Decoder::feed |
| OSC scanning whose event consumer can fail or pause | Decoder::try_feed |
| VT context and original frame bytes | The terminal-stream example below |
Reports borrow their input. Messages and titles stay base64 encoded until you decode them, but the parser checks UTF-8 and rejects control characters first. In a decoder callback, copy or decode what you need before the callback returns.
§Handle the result
The two parsing functions return:
Ok(Some(event))for an accepted report, query, or capability reply.Ok(None)for a report with a missing or unknown state, or an invalid record id.Err(error)for invalid framing, invalid text, or an exceeded limit.
Invalid app ids and progress values are treated as absent. Complete frames
are limited to 4096 bytes; decoded messages to 2048 bytes and titles to 192.
Decoder::feed calls you for accepted events and errors, and skips ignored reports.
Decoder::try_feed stops when its callback returns Err. The callback can use
any error type or a simple stop value such as (). Its stream::Error provides
consumed() for the number of bytes consumed, get_ref() to inspect the original
value, and into_inner() to recover it by value. The wrapper implements
core::error::Error with a source chain when the callback error implements
core::error::Error + 'static.
To propagate only the callback error, use .map_err(stream::Error::into_inner)?.
This also works with callbacks returning anyhow::Result or boxed errors.
Keep the wrapper when you need the consumed position to resume.
Resume on the same decoder with &input[failure.consumed()..]. The delivered
event stays consumed, so copy any data you need before returning an error.
Callback effects are not rolled back. If feeding stops at an oversized frame,
resuming drains the rest of that frame without reporting its error again.
The Decoder::try_feed API documentation includes a stop/resume example.
Splitting input across calls does not change the event or error sequence.
An empty input changes nothing. These rules also apply when you stop and resume
with try_feed.
Capability replies skip unknown names and pairs. Missing lists use revision 0.4
defaults; empty lists remain empty. A bare Event::Query can also be a default
reply, so use stream direction and pending-query state to tell them apart.
Equality compares parsed representations. Reports with padded and unpadded base64 can compare unequal even when their decoded text matches. Compare decoded fields for report meaning. Capability equality includes the original lists; use their iterators or support queries to compare known capabilities.
The parser returns events without keeping records. For current status and terminal cleanup, use osc7501-store.
§Observe a terminal stream
The supported terminal-stream example forwards stdin unchanged to stdout and reports OSC 7501 observations on stderr:
cargo run -p osc7501-parser --example terminal_stream --quiet < recording.bin > forwarded.binUse this example when you need VT cancellation, original frame bytes, or full
reset notifications. Decoder is an OSC scanner; it does not track the complete
VT parser state or retain unrelated output. If your host already has a terminal
parser, use its dispatcher and pass the original OSC body to parse_body.
The example uses vte 0.15 with default features disabled and bounded storage.
It recognizes literal ESC-] frames ending in BEL or ESC-backslash. Cancelled,
oversized, and unfinished prefixes pass through without becoming reports.
Unknown OSCs, ignored reports, rejected reports, and ordinary output keep their
original bytes. It follows vte’s UTF-8 terminal model; it does not decode tmux
passthrough or eight-bit OSC/ST framing.
Adapter::try_feed delivers borrowed segments in order. A callback can parse,
copy, forward, or replace each segment. After a callback stops, resume on the
same adapter at error.consumed(). A retained prefix can be delivered before
any new byte is consumed, so this offset can be zero. The delivered segment
stays consumed. Call finish at EOF to flush pending bytes and reset VT state
before an independent stream. The filter aborts on I/O errors; a failed write
can leave partial output and is not retried as a whole segment.
The adapter remains example code. vte is a development dependency; the parser
library keeps its existing dependencies and allocation-free no_std API.
See the API documentation for the full interface.
Re-exports§
pub use stream::Decoder;
Modules§
- stream
- Streaming decoder and resumable callback errors.
Structs§
- AppId
- A validated stable application identifier.
- Capabilities
- Feature detection reply. Unknown state and kind names are skipped.
- Encoded
Text - Base64 text whose UTF-8 and absence of controls have already been validated. Equality compares the encoded form: padded and unpadded spellings can decode to the same text and still compare unequal.
- Progress
- A validated percentage in the inclusive range 0..=100.
- Record
Id - A validated hierarchical identifier. Root is represented by
None. - Report
- A validated report. Missing fields remove the prior record’s fields. Equality compares parsed fields, including the original base64 text. Compare decoded text when checking whether reports have the same meaning.
Enums§
- Action
- An update or a subtree removal.
- Error
- Failure to validate a value, parse OSC 7501 input, or decode its text.
- Event
- A recognized protocol event.
- Kind
- Why a blocked record needs the user.
- Limit
- A hard protocol bound that was exceeded.
- State
- A record’s state. Clearing is represented separately by
Action::Clear.
Constants§
- MAX_APP
- Maximum application identifier length.
- MAX_
DEPTH - Maximum number of identifier segments.
- MAX_ID
- Maximum record identifier length.
- MAX_KEY
- Maximum key length.
- MAX_
MESSAGE - Maximum decoded message length.
- MAX_
MESSAGE_ ENCODED - Maximum encoded message length.
- MAX_
SEGMENT - Maximum identifier segment length.
- MAX_
SEQUENCE - Maximum complete sequence size, including OSC and terminator.
- MAX_
TITLE - Maximum decoded title length.
- MAX_
TITLE_ ENCODED - Maximum encoded title length.
Functions§
- parse_
body - Parses a body after a terminal dispatcher has consumed
OSC 7501;and ST. - parse_
sequence - Parses exactly one OSC 7501 sequence terminated by BEL or ESC-backslash.