From 17fc6b3eda370f99fee48420532ada8b497ecd8c Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 27 Oct 2019 08:07:09 -0400 Subject: docs --- src/creator.rs | 17 +++++++++++++++++ src/error.rs | 8 ++++++++ src/frame.rs | 13 +++++++++++++ src/lib.rs | 6 ++++++ src/parser.rs | 14 ++++++++++++++ src/reader.rs | 8 ++++++++ src/writer.rs | 23 +++++++++++++++++++++++ 7 files changed, 89 insertions(+) diff --git a/src/creator.rs b/src/creator.rs index fb228dd..c0f9b76 100644 --- a/src/creator.rs +++ b/src/creator.rs @@ -1,17 +1,34 @@ +/// Creates ttyrec frames. +/// +/// A ttyrec file is a stream of concatenated frames. This struct creates +/// `Frame` objects, which can be serialized to bytes using their `try_from` +/// implementation, and then a ttyrec file can be generated by concatenating +/// those byte strings. #[derive(Debug, Clone)] pub struct Creator { base_time: Option, } impl Creator { + /// Creates a new `Creator` instance. pub fn new() -> Self { Default::default() } + /// Returns a new `Frame` object containing the given data. + /// + /// Equivalent to calling `frame_at` and passing + /// `std::time::Instant::now()` as the `cur_time` parameter. pub fn frame(&mut self, data: &[u8]) -> crate::frame::Frame { self.frame_at(std::time::Instant::now(), data) } + /// Returns a new `Frame` object containing the given data at the given + /// time. + /// + /// Note that this is not guaranteed to do the correct thing unless the + /// `cur_time` parameters given in each `frame_at` call are + /// non-decreasing. pub fn frame_at( &mut self, cur_time: std::time::Instant, diff --git a/src/error.rs b/src/error.rs index aa315e6..975889b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,18 +1,26 @@ +/// Errors potentially returned by this crate. #[derive(Debug, snafu::Snafu)] #[snafu(visibility(pub))] pub enum Error { + /// eof #[snafu(display("eof"))] EOF, + /// failed to create ttyrec frame: got N bytes of data but ttyrec frames + /// can be at most M bytes #[snafu(display("failed to create ttyrec frame: got {} bytes of data, but ttyrec frames can be at most {} bytes", input, u32::max_value()))] FrameTooBig { input: usize }, + /// failed to create ttyrec frame: got N seconds but ttyrec frames can be + /// at most M seconds #[snafu(display("failed to create ttyrec frame: got {} seconds, but ttyrecs can be at most {} seconds", input, u32::max_value()))] FrameTooLong { input: u64 }, + /// failed to read from file #[snafu(display("failed to read from file: {}", source))] ReadFile { source: tokio::io::Error }, + /// failed to write to file #[snafu(display("failed to write to file: {}", source))] WriteFile { source: tokio::io::Error }, } diff --git a/src/frame.rs b/src/frame.rs index 7558470..17c6c5a 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,6 +1,19 @@ +/// Represents a single ttyrec frame. +/// +/// Ttyrec files are a raw concatenation of frames. Note that the `time` field +/// in each frame is the time since the start of the entire file, and it is +/// invalid for the `time` fields in a ttyrec file to be decreasing. +/// +/// Frame objects are typically created via the `Creator`, `Parser`, or +/// `Reader` classes. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Frame { + /// Amount of time passed since the start of the ttyrec file. + /// + /// Note that this is *not* the amount of time since the previous frame. pub time: std::time::Duration, + + /// Bytes emitted at the given time. pub data: Vec, } diff --git a/src/lib.rs b/src/lib.rs index 7324edd..1de8daa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,9 @@ +//! This crate contains helpers for reading and writing +//! [ttyrec](https://en.wikipedia.org/wiki/Ttyrec) files. +//! +//! `Parser` and `Creator` can be used to read and write files manually, and +//! `Reader` and `Writer` are helpers to provide a nicer API for asynchronous +//! applications using `tokio`. mod creator; pub use creator::Creator; mod error; diff --git a/src/parser.rs b/src/parser.rs index d3c3861..a473931 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -18,6 +18,13 @@ impl Header { } } +/// Parses ttyrec streams. +/// +/// Designed to be able to be used in a streaming/asynchronous fashion. As you +/// read bytes from the ttyrec stream (whether from a file or whatever else), +/// call the `add_bytes` method to add them to the internal buffer. At any +/// point, you can call `next_frame` to then return the next complete frame if +/// one has been read. #[derive(Debug, Clone)] pub struct Parser { reading: std::collections::VecDeque, @@ -25,14 +32,21 @@ pub struct Parser { } impl Parser { + /// Create a new `Parser`. pub fn new() -> Self { Default::default() } + /// Add more bytes to the internal buffer. pub fn add_bytes(&mut self, bytes: &[u8]) { self.reading.extend(bytes.iter()); } + /// Try to read a frame from the internal buffer. + /// + /// If a complete frame is found, the bytes for that frame will be removed + /// from the internal buffer and the frame object will be returned. If a + /// complete frame is not found, this method will return `None`. pub fn next_frame(&mut self) -> Option { let header = if let Some(header) = &self.read_state { header diff --git a/src/reader.rs b/src/reader.rs index 4d122f9..fd87cd5 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -1,5 +1,6 @@ use snafu::ResultExt as _; +/// Reads ttyrec frames from a `tokio::io::AsyncRead` instance. pub struct Reader { reader: R, parser: crate::parser::Parser, @@ -8,6 +9,7 @@ pub struct Reader { } impl Reader { + /// Creates a new `Reader` from a `tokio::io::AsyncRead` instance. pub fn new(reader: R) -> Self { Self { reader, @@ -17,6 +19,12 @@ impl Reader { } } + /// Polls to see if a new frame can be read. + /// + /// Returns `Ok(Async::Ready(Some(frame)))` if a frame is available, + /// `Ok(Async::Ready(None))` if the underlying reader is done, and + /// `Ok(Async::NotReady)` if not enough bytes have been read for a full + /// frame. pub fn poll_read( &mut self, ) -> futures::Poll, crate::error::Error> { diff --git a/src/writer.rs b/src/writer.rs index 109aba9..8f79737 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,5 +1,6 @@ use snafu::ResultExt as _; +/// Writes ttyrec frames to a `tokio::io::AsyncWrite` instance. pub struct Writer { writer: W, creator: crate::creator::Creator, @@ -7,6 +8,7 @@ pub struct Writer { } impl Writer { + /// Creates a new `Writer` from a `tokio::io::AsyncWrite` instance. pub fn new(writer: W) -> Self { Self { writer, @@ -15,10 +17,22 @@ impl Writer { } } + /// Generates a new ttyrec frame with the given data. + /// + /// Equivalent to calling `frame_at` and passing + /// `std::time::Instant::now()` as the `time` parameter. pub fn frame(&mut self, data: &[u8]) -> crate::error::Result<()> { self.frame_at(std::time::Instant::now(), data) } + /// Generates a new ttyrec frame with the given data at the given time. + /// + /// The frame data will be stored on this object until written out by + /// calls to `poll_write`. + /// + /// Note that this is not guaranteed to do the correct thing unless the + /// `cur_time` parameters given in each `frame_at` call are + /// non-decreasing. pub fn frame_at( &mut self, time: std::time::Instant, @@ -30,6 +44,11 @@ impl Writer { Ok(()) } + /// Attempt to write serialized ttyrec frames to the underlying writer. + /// + /// Writes data from the previous calls to `frame` and `frame_at`. Returns + /// `Ok(Async::Ready(()))` if all bytes were written, and + /// `Ok(Async::NotReady)` otherwise. pub fn poll_write(&mut self) -> futures::Poll<(), crate::error::Error> { loop { if self.to_write.is_empty() { @@ -54,6 +73,10 @@ impl Writer { } } + /// Returns `true` if there are still bytes that need to be written. + /// + /// It is only necessary to call `poll_write` if this method returns + /// `true`. pub fn needs_write(&self) -> bool { !self.to_write.is_empty() } -- cgit v1.2.3-54-g00ecf