asciicast-rs
A library to parse asciicast file
format files across all asciicast
versions.
Versions supported
Why support all 3?
I wanted to be able to parse old files as well for another project I'm working on called acdc.
Installation
You can parse from:
- a byte slice using
from_slice - a
BufReadusingfrom_reader - a file using
from_path
They all return Result<_, asciicast_rs::Error>.
Parsing a known version
The version is part of the type system, so you can parse directly into Asciicast<V>.
use ;
let recording = b"{\"version\":2,\"width\":80,\"height\":24}\n[0.5,\"o\",\"hello\"]\n";
let cast = from_slice.expect;
println!;
for event in &cast.events
To read from a file instead, use Asciicast::<V2>::from_path("recording.cast").
Auto-detecting the version
When the version is not known ahead of time, use AsciicastVersioned, which detects it
from the content and yields the matching variant, each wrapping a fully typed
Asciicast<V>.
use AsciicastVersioned;
let recording = b"{\"version\":2,\"width\":80,\"height\":24}\n";
match from_slice.expect
Streaming events (v2 / v3)
from_slice/from_path/from_reader eagerly collect every event into a Vec. For long
recordings, you can instead use a Reader (or wrappers like v2::stream and
v3::stream) which yields a Result<Event, _> per line as an Iterator, so the whole
recording is never held in memory at once. You can construct one with Reader::<V, _>::open or one of the wrappers mentioned.
[!NOTE] Only the newline-delimited versions (v2, v3) implement
Streamable, soReader<V1, _>is a compile error (v1 is a single JSON document and is always parsed eagerly).
use v2;
let recording: & = b"{\"version\":2,\"width\":80,\"height\":24}\n[0.5,\"o\",\"hi\"]\n";
let reader = stream.expect;
println!;
for event in reader
// If you have the stream and want to materialise the eager `Asciicast` you can do:
let eager = stream
.and_then
.expect;
assert_eq!;
Working with the parsed data
use ;
let recording = b"{\"version\":3,\"term\":{\"cols\":80,\"rows\":24}}\n";
let cast = from_slice.expect;
assert_eq!;
Absolute timestamps
Timing differs by version (see Data model), so absolute_times normalises
it for you: it pairs each event with its absolute time in seconds since the start,
accumulating relative entries (v1, v3) and passing v2's already-absolute times through.
use ;
let recording = b"{\"version\":3,\"term\":{\"cols\":80,\"rows\":24}}\n[0.1,\"o\",\"a\"]\n[0.2,\"o\",\"b\"]\n";
let cast = from_slice.expect;
for in cast.absolute_times
Reader::absolute_times is the streaming counterpart, yielding Result<(f64, Event), _>
so you get absolute timestamps without buffering the recording.
Data model
Asciicast<V>is{ header, events }, parameterised by a version marker (V1,V2,V3).- Each version has its own
Headerand event type underasciicast_rs::{v1, v2, v3}. Events expose a typed payload plus accessors (as_output,as_input,as_marker,as_resize, and alsoas_exitfor v3). - Shared types live in
asciicast_rs::common(Theme,Rgb,Resize,ExitStatus,Env, and the colour error types). - Timing semantics follow the spec: v2 event
timeis absolute (seconds since start), while v1 framedelayand v3 eventintervalare relative to the previous entry. UseAsciicast::absolute_timesto iterate events with a uniform absolute timestamp.
[!NOTE] In v1, the nomenclature used is attributes and frames instead of header and events (roughly). I thought that keeping to header and events across the versions was fine but isn't strictly accurate.
Feature flags
-
chrono(off by default) — adds atimestamp_datetime()accessor to the v2 and v3 headers, returning the recording's start time as achrono::DateTime<Utc>:
What this crate is not
A way to serialize asciicast format to files. Reason being that I wanted this crate to
start with the smallest possible "features", whilst being complete in terms of parsing, in
case one day the asciinema project decides to extract their serialization and parsing
into its own library and crate.
Motivation
I needed a parser for asciicast files but realized there wasn't one (that I could easily
find) that was obvious I should use. More notes on what I found:
-
asciinemais built in rust but unfortunately it doesn't expose theasciicastformat publicly as a library. -
There was also a library named
asciicastbut unfortunately doesn't seem to get any more updates.
Therefore I decided to create this crate to try to become the canonical rust library for
parsing asciicast format. If one day asciinema decides to provide a public crate then
I'd be happy to stop work here.