mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
add function to load Cp437Grid from str
This commit is contained in:
parent
21cc7e3f12
commit
03f7495695
|
@ -4,18 +4,13 @@ use crate::{
|
||||||
command_code::CommandCode,
|
command_code::CommandCode,
|
||||||
compression::into_decompressed,
|
compression::into_decompressed,
|
||||||
packet::{Header, Packet},
|
packet::{Header, Packet},
|
||||||
Brightness, BrightnessGrid, CompressionCode, Origin, PixelGrid, Pixels,
|
Brightness, BrightnessGrid, CompressionCode, Cp437Grid, Origin, PixelGrid,
|
||||||
PrimitiveGrid, SpBitVec, Tiles, TILE_SIZE,
|
Pixels, PrimitiveGrid, SpBitVec, Tiles, TILE_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Type alias for documenting the meaning of the u16 in enum values
|
/// Type alias for documenting the meaning of the u16 in enum values
|
||||||
pub type Offset = usize;
|
pub type Offset = usize;
|
||||||
|
|
||||||
/// A grid containing codepage 437 characters.
|
|
||||||
///
|
|
||||||
/// The encoding is currently not enforced.
|
|
||||||
pub type Cp437Grid = PrimitiveGrid<u8>;
|
|
||||||
|
|
||||||
/// A low-level display command.
|
/// A low-level display command.
|
||||||
///
|
///
|
||||||
/// This struct and associated functions implement the UDP protocol for the display.
|
/// This struct and associated functions implement the UDP protocol for the display.
|
||||||
|
@ -92,9 +87,8 @@ pub enum Command {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use servicepoint::{Command, Connection, Cp437Grid, Origin};
|
/// # use servicepoint::{Command, Connection, Cp437Grid, Origin};
|
||||||
/// # let connection = Connection::open("127.0.0.1:2342").unwrap();
|
/// # let connection = Connection::Fake;
|
||||||
/// let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'].map(move |c| c as u8);
|
/// let grid = Cp437Grid::load_ascii("Hello\nWorld", 5, false).unwrap();
|
||||||
/// let grid = Cp437Grid::load(5, 2, &chars);
|
|
||||||
/// connection.send(Command::Cp437Data(Origin::new(2, 2), grid)).unwrap();
|
/// connection.send(Command::Cp437Data(Origin::new(2, 2), grid)).unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
Cp437Data(Origin<Tiles>, Cp437Grid),
|
Cp437Data(Origin<Tiles>, Cp437Grid),
|
||||||
|
|
100
crates/servicepoint/src/cp437.rs
Normal file
100
crates/servicepoint/src/cp437.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
use crate::cp437::Cp437LoadError::InvalidChar;
|
||||||
|
use crate::{Grid, PrimitiveGrid};
|
||||||
|
|
||||||
|
/// A grid containing codepage 437 characters.
|
||||||
|
///
|
||||||
|
/// The encoding is currently not enforced.
|
||||||
|
pub type Cp437Grid = PrimitiveGrid<u8>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Cp437LoadError {
|
||||||
|
InvalidChar { index: usize, char: char },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cp437Grid {
|
||||||
|
/// Load an ASCII-only [&str] into a [Cp437Grid] of specified width.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// - for width == 0
|
||||||
|
/// - on empty strings
|
||||||
|
pub fn load_ascii(
|
||||||
|
value: &str,
|
||||||
|
width: usize,
|
||||||
|
wrap: bool,
|
||||||
|
) -> Result<Self, Cp437LoadError> {
|
||||||
|
assert!(width > 0);
|
||||||
|
assert!(!value.is_empty());
|
||||||
|
|
||||||
|
let mut chars = {
|
||||||
|
let mut x = 0;
|
||||||
|
let mut y = 0;
|
||||||
|
|
||||||
|
for (index, char) in value.chars().enumerate() {
|
||||||
|
if !char.is_ascii() {
|
||||||
|
return Err(InvalidChar { index, char });
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_lf = char == '\n';
|
||||||
|
if is_lf || (wrap && x == width) {
|
||||||
|
y += 1;
|
||||||
|
x = 0;
|
||||||
|
if is_lf {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cp437Grid::new(width, y + 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut x = 0;
|
||||||
|
let mut y = 0;
|
||||||
|
for char in value.chars().map(move |c| c as u8) {
|
||||||
|
let is_lf = char == b'\n';
|
||||||
|
if is_lf || (wrap && x == width) {
|
||||||
|
y += 1;
|
||||||
|
x = 0;
|
||||||
|
if is_lf {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if wrap || x < width {
|
||||||
|
chars.set(x, y, char);
|
||||||
|
}
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn load_ascii_nowrap() {
|
||||||
|
let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
|
||||||
|
.map(move |c| c as u8);
|
||||||
|
let expected = Cp437Grid::load(5, 2, &chars);
|
||||||
|
|
||||||
|
let actual = Cp437Grid::load_ascii("Hello,\nWorld!", 5, false).unwrap();
|
||||||
|
// comma will be removed because line is too long and wrap is off
|
||||||
|
assert_eq!(actual, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn load_ascii_wrap() {
|
||||||
|
let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
|
||||||
|
.map(move |c| c as u8);
|
||||||
|
let expected = Cp437Grid::load(5, 2, &chars);
|
||||||
|
|
||||||
|
let actual = Cp437Grid::load_ascii("HelloWorld", 5, true).unwrap();
|
||||||
|
// line break will be added
|
||||||
|
assert_eq!(actual, expected);
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,9 +41,10 @@ pub use bitvec;
|
||||||
use bitvec::prelude::{BitVec, Msb0};
|
use bitvec::prelude::{BitVec, Msb0};
|
||||||
|
|
||||||
pub use crate::brightness::{Brightness, BrightnessGrid};
|
pub use crate::brightness::{Brightness, BrightnessGrid};
|
||||||
pub use crate::command::{Command, Cp437Grid, Offset};
|
pub use crate::command::{Command, Offset};
|
||||||
pub use crate::compression_code::CompressionCode;
|
pub use crate::compression_code::CompressionCode;
|
||||||
pub use crate::connection::Connection;
|
pub use crate::connection::Connection;
|
||||||
|
pub use crate::cp437::Cp437Grid;
|
||||||
pub use crate::data_ref::DataRef;
|
pub use crate::data_ref::DataRef;
|
||||||
pub use crate::grid::Grid;
|
pub use crate::grid::Grid;
|
||||||
pub use crate::origin::{Origin, Pixels, Tiles};
|
pub use crate::origin::{Origin, Pixels, Tiles};
|
||||||
|
@ -58,6 +59,7 @@ mod command_code;
|
||||||
mod compression;
|
mod compression;
|
||||||
mod compression_code;
|
mod compression_code;
|
||||||
mod connection;
|
mod connection;
|
||||||
|
mod cp437;
|
||||||
mod data_ref;
|
mod data_ref;
|
||||||
mod grid;
|
mod grid;
|
||||||
mod origin;
|
mod origin;
|
||||||
|
|
|
@ -40,7 +40,9 @@ pub unsafe extern "C" fn sp_cp437_grid_new(
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
) -> *mut SPCp437Grid {
|
) -> *mut SPCp437Grid {
|
||||||
Box::into_raw(Box::new(SPCp437Grid(servicepoint::Cp437Grid::new(width, height))))
|
Box::into_raw(Box::new(SPCp437Grid(servicepoint::Cp437Grid::new(
|
||||||
|
width, height,
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a `SPCp437Grid` with the specified dimensions from the provided data.
|
/// Loads a `SPCp437Grid` with the specified dimensions from the provided data.
|
||||||
|
@ -67,7 +69,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load(
|
||||||
data_length: usize,
|
data_length: usize,
|
||||||
) -> *mut SPCp437Grid {
|
) -> *mut SPCp437Grid {
|
||||||
let data = std::slice::from_raw_parts(data, data_length);
|
let data = std::slice::from_raw_parts(data, data_length);
|
||||||
Box::into_raw(Box::new(SPCp437Grid(servicepoint::Cp437Grid::load(width, height, data))))
|
Box::into_raw(Box::new(SPCp437Grid(servicepoint::Cp437Grid::load(
|
||||||
|
width, height, data,
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clones a `SPCp437Grid`.
|
/// Clones a `SPCp437Grid`.
|
||||||
|
|
Loading…
Reference in a new issue