diff --git a/Cargo.lock b/Cargo.lock index 2f4673a..0009b65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,6 +35,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "embedded-io" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" + [[package]] name = "env_logger" version = "0.8.4" @@ -326,8 +332,9 @@ checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "vt100" -version = "0.16.2" +version = "0.16.3" dependencies = [ + "embedded-io", "itoa", "nix", "quickcheck", diff --git a/Cargo.toml b/Cargo.toml index db35e20..c9b2fa5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vt100" -version = "0.16.2" +version = "0.16.3" authors = ["Jesse Luehrs "] edition = "2021" rust-version = "1.70" @@ -15,9 +15,10 @@ license = "MIT" include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] [dependencies] +embedded-io = { version = "0.7.1", optional = true } itoa = "1.0.15" unicode-width = "0.2.1" -vte = "0.15.0" +vte = { version = "0.15.0", default-features = false } [dev-dependencies] nix = { version = "0.30.1", features = ["term"] } @@ -26,3 +27,7 @@ rand = "0.9" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" terminal_size = "0.4.2" + +[features] +default = ["std"] +std = ["vte/std"] diff --git a/src/attrs.rs b/src/attrs.rs index e5044f2..8cb52d8 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -1,4 +1,5 @@ use crate::term::BufWrite as _; +use alloc::vec::Vec; /// Represents a foreground or background color for cells. #[derive(Eq, PartialEq, Debug, Copy, Clone, Default)] diff --git a/src/cell.rs b/src/cell.rs index c000cf3..3870904 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -14,7 +14,7 @@ pub struct Cell { len: u8, attrs: crate::attrs::Attrs, } -const _: () = assert!(std::mem::size_of::() == 32); +const _: () = assert!(core::mem::size_of::() == 32); impl PartialEq for Cell { fn eq(&self, other: &Self) -> bool { @@ -87,7 +87,7 @@ impl Cell { #[allow(clippy::missing_panics_doc)] #[must_use] pub fn contents(&self) -> &str { - std::str::from_utf8(&self.contents[..self.len()]).unwrap() + core::str::from_utf8(&self.contents[..self.len()]).unwrap() } /// Returns whether the cell contains any text data. diff --git a/src/grid.rs b/src/grid.rs index 7768d06..e33f8f5 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -1,4 +1,5 @@ use crate::term::BufWrite as _; +use alloc::{collections::VecDeque, string::String, vec::Vec}; #[derive(Clone, Debug)] pub struct Grid { @@ -10,7 +11,7 @@ pub struct Grid { scroll_bottom: u16, origin_mode: bool, saved_origin_mode: bool, - scrollback: std::collections::VecDeque, + scrollback: VecDeque, scrollback_len: usize, scrollback_offset: usize, } @@ -26,7 +27,7 @@ impl Grid { scroll_bottom: size.rows - 1, origin_mode: false, saved_origin_mode: false, - scrollback: std::collections::VecDeque::new(), + scrollback: VecDeque::new(), scrollback_len, scrollback_offset: 0, } @@ -35,7 +36,7 @@ impl Grid { pub fn allocate_rows(&mut self) { if self.rows.is_empty() { self.rows.extend( - std::iter::repeat_with(|| { + core::iter::repeat_with(|| { crate::row::Row::new(self.size.cols) }) .take(usize::from(self.size.rows)), diff --git a/src/lib.rs b/src/lib.rs index 19746a9..a504529 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ //! ); //! ``` +#![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] #![warn(clippy::cargo)] #![warn(clippy::pedantic)] @@ -47,6 +48,9 @@ #![allow(clippy::too_many_lines)] #![allow(clippy::type_complexity)] +#[macro_use] +extern crate alloc; + mod attrs; mod callbacks; mod cell; diff --git a/src/parser.rs b/src/parser.rs index c81495b..b3474f7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -84,6 +84,7 @@ impl Default for Parser { } } +#[cfg(feature = "std")] impl std::io::Write for Parser { fn write(&mut self, buf: &[u8]) -> std::io::Result { self.process(buf); @@ -94,3 +95,30 @@ impl std::io::Write for Parser { Ok(()) } } + +#[cfg(feature = "embedded-io")] +impl embedded_io::ErrorType for Parser { + type Error = core::convert::Infallible; +} + +#[cfg(feature = "embedded-io")] +impl embedded_io::Write for Parser { + fn write( + &mut self, + buf: &[u8], + ) -> core::result::Result { + self.process(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + Ok(()) + } +} + +#[cfg(feature = "embedded-io")] +impl embedded_io::WriteReady for Parser { + fn write_ready(&mut self) -> core::result::Result { + Ok(true) + } +} diff --git a/src/perform.rs b/src/perform.rs index e36cfd8..b2ac805 100644 --- a/src/perform.rs +++ b/src/perform.rs @@ -1,3 +1,5 @@ +use alloc::vec::Vec; + const BASE64: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; const CLIPBOARD_SELECTOR: &[u8] = b"cpqs01234567"; diff --git a/src/row.rs b/src/row.rs index 4ae8d86..c4310d3 100644 --- a/src/row.rs +++ b/src/row.rs @@ -1,4 +1,5 @@ use crate::term::BufWrite as _; +use alloc::{string::String, vec::Vec}; #[derive(Clone, Debug)] pub struct Row { diff --git a/src/screen.rs b/src/screen.rs index 7dfec97..58006dd 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -1,4 +1,5 @@ use crate::term::BufWrite as _; +use alloc::{string::String, vec::Vec}; use unicode_width::UnicodeWidthChar as _; const MODE_APPLICATION_KEYPAD: u8 = 0b0000_0001; @@ -172,7 +173,7 @@ impl Screen { end_col: u16, ) -> String { match start_row.cmp(&end_row) { - std::cmp::Ordering::Less => { + core::cmp::Ordering::Less => { let (_, cols) = self.size(); let mut contents = String::new(); for (i, row) in self @@ -203,7 +204,7 @@ impl Screen { } contents } - std::cmp::Ordering::Equal => { + core::cmp::Ordering::Equal => { if start_col < end_col { self.rows(start_col, end_col - start_col) .nth(usize::from(start_row)) @@ -212,7 +213,7 @@ impl Screen { String::new() } } - std::cmp::Ordering::Greater => String::new(), + core::cmp::Ordering::Greater => String::new(), } } diff --git a/src/term.rs b/src/term.rs index b6b898c..7acc617 100644 --- a/src/term.rs +++ b/src/term.rs @@ -1,5 +1,7 @@ // TODO: read all of this from terminfo +use alloc::vec::Vec; + pub trait BufWrite { fn write_buf(&self, buf: &mut Vec); } diff --git a/tests/write.rs b/tests/write.rs index 0b1d5fe..5ccb004 100644 --- a/tests/write.rs +++ b/tests/write.rs @@ -1,5 +1,13 @@ +#![cfg(any(feature = "std", feature = "embedded-io"))] + +#[cfg(feature = "std")] use std::io::Write as _; +// Caveat: if both embedded-io and std features are specified, we only test +// the std feature. +#[cfg(all(feature = "embedded-io", not(feature = "std")))] +use embedded_io::Write as _; + #[test] fn write_text() { let mut parser = vt100::Parser::default();