diff --git a/crates/servicepoint/src/char_grid.rs b/crates/servicepoint/src/char_grid.rs index 225474e..1a9045c 100644 --- a/crates/servicepoint/src/char_grid.rs +++ b/crates/servicepoint/src/char_grid.rs @@ -1,5 +1,5 @@ use crate::primitive_grid::SeriesError; -use crate::PrimitiveGrid; +use crate::{Grid, PrimitiveGrid}; /// A grid containing UTF-8 characters. pub type CharGrid = PrimitiveGrid; @@ -42,9 +42,57 @@ impl CharGrid { } } +impl From<&str> for CharGrid { + fn from(value: &str) -> Self { + let value = value.replace("\r\n", "\n"); + let mut lines = value + .split('\n') + .map(move |line| line.trim_end()) + .collect::>(); + let width = + lines.iter().fold(0, move |a, x| std::cmp::max(a, x.len())); + + while lines.last().is_some_and(move |line| line.is_empty()) { + _ = lines.pop(); + } + + let mut grid = Self::new(width, lines.len()); + for (y, line) in lines.iter().enumerate() { + for (x, char) in line.chars().enumerate() { + grid.set(x, y, char); + } + } + + grid + } +} + +impl From for CharGrid { + fn from(value: String) -> Self { + CharGrid::from(&*value) + } +} + +impl From<&CharGrid> for String { + fn from(value: &CharGrid) -> Self { + value + .iter_rows() + .map(move |chars| { + chars + .collect::() + .replace('\0', " ") + .trim_end() + .to_string() + }) + .collect::>() + .join("\n") + } +} + #[cfg(test)] mod test { use super::*; + use crate::Grid; #[test] fn col_str() { let mut grid = CharGrid::new(2, 3); @@ -69,4 +117,13 @@ mod test { assert_eq!(grid.set_row_str(1, "ab"), Ok(())); assert_eq!(grid.get_row_str(1), Some(String::from("ab"))); } + + #[test] + fn str_to_char_grid() { + let original = "Hello\r\nWorld!\n...\n"; + let grid = CharGrid::from(original); + assert_eq!(3, grid.height()); + let actual = String::from(&grid); + assert_eq!("Hello\nWorld!\n...", actual); + } } diff --git a/crates/servicepoint/src/cp437.rs b/crates/servicepoint/src/cp437.rs index 1c1fba9..9a81717 100644 --- a/crates/servicepoint/src/cp437.rs +++ b/crates/servicepoint/src/cp437.rs @@ -88,8 +88,8 @@ pub use feature_cp437::*; #[cfg(feature = "cp437")] mod feature_cp437 { - use crate::CharGrid; use super::*; + use crate::CharGrid; /// An array of 256 elements, mapping most of the CP437 values to UTF-8 characters /// @@ -147,53 +147,6 @@ mod feature_cp437 { } } - impl From<&str> for CharGrid { - fn from(value: &str) -> Self { - let value = value.replace("\r\n", "\n"); - let mut lines = value - .split('\n') - .map(move |line| line.trim_end()) - .collect::>(); - let width = - lines.iter().fold(0, move |a, x| std::cmp::max(a, x.len())); - - while lines.last().is_some_and(move |line| line.is_empty()) { - _ = lines.pop(); - } - - let mut grid = Self::new(width, lines.len()); - for (y, line) in lines.iter().enumerate() { - for (x, char) in line.chars().enumerate() { - grid.set(x, y, char); - } - } - - grid - } - } - - impl From for CharGrid { - fn from(value: String) -> Self { - CharGrid::from(&value) - } - } - - impl From<&CharGrid> for String { - fn from(value: &CharGrid) -> Self { - value - .iter_rows() - .map(move |chars| { - chars - .collect::() - .replace('\0', " ") - .trim_end() - .to_string() - }) - .collect::>() - .join("\n") - } - } - /// Convert the provided bytes to UTF-8. pub fn cp437_to_str(cp437: &[u8]) -> String { cp437.iter().map(move |char| cp437_to_char(*char)).collect() @@ -258,8 +211,8 @@ mod tests { #[cfg(test)] #[cfg(feature = "cp437")] mod tests_feature_cp437 { - use crate::CharGrid; use super::*; + use crate::CharGrid; #[test] fn round_trip_cp437() { @@ -303,13 +256,4 @@ mod tests_feature_cp437 { fn convert_invalid() { assert_eq!(cp437_to_char(char_to_cp437('😜')), '?'); } - - #[test] - fn str_to_char_grid() { - let original = "Hello\r\nWorld!\n...\n"; - let grid = CharGrid::from(original); - assert_eq!(3, grid.height()); - let actual = String::from(&grid); - assert_eq!("Hello\nWorld!\n...", actual); - } }