add function to load Cp437Grid from str
This commit is contained in:
		
							parent
							
								
									21cc7e3f12
								
							
						
					
					
						commit
						03f7495695
					
				
					 4 changed files with 113 additions and 13 deletions
				
			
		|  | @ -4,18 +4,13 @@ use crate::{ | |||
|     command_code::CommandCode, | ||||
|     compression::into_decompressed, | ||||
|     packet::{Header, Packet}, | ||||
|     Brightness, BrightnessGrid, CompressionCode, Origin, PixelGrid, Pixels, | ||||
|     PrimitiveGrid, SpBitVec, Tiles, TILE_SIZE, | ||||
|     Brightness, BrightnessGrid, CompressionCode, Cp437Grid, Origin, PixelGrid, | ||||
|     Pixels, PrimitiveGrid, SpBitVec, Tiles, TILE_SIZE, | ||||
| }; | ||||
| 
 | ||||
| /// Type alias for documenting the meaning of the u16 in enum values
 | ||||
| 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.
 | ||||
| ///
 | ||||
| /// This struct and associated functions implement the UDP protocol for the display.
 | ||||
|  | @ -92,9 +87,8 @@ pub enum Command { | |||
|     ///
 | ||||
|     /// ```rust
 | ||||
|     /// # use servicepoint::{Command, Connection, Cp437Grid, Origin};
 | ||||
|     /// # let connection = Connection::open("127.0.0.1:2342").unwrap();
 | ||||
|     /// let chars = ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'].map(move |c| c as u8);
 | ||||
|     /// let grid = Cp437Grid::load(5, 2, &chars);
 | ||||
|     /// # let connection = Connection::Fake;
 | ||||
|     /// let grid = Cp437Grid::load_ascii("Hello\nWorld", 5, false).unwrap();
 | ||||
|     /// connection.send(Command::Cp437Data(Origin::new(2, 2), grid)).unwrap();
 | ||||
|     /// ```
 | ||||
|     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}; | ||||
| 
 | ||||
| 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::connection::Connection; | ||||
| pub use crate::cp437::Cp437Grid; | ||||
| pub use crate::data_ref::DataRef; | ||||
| pub use crate::grid::Grid; | ||||
| pub use crate::origin::{Origin, Pixels, Tiles}; | ||||
|  | @ -58,6 +59,7 @@ mod command_code; | |||
| mod compression; | ||||
| mod compression_code; | ||||
| mod connection; | ||||
| mod cp437; | ||||
| mod data_ref; | ||||
| mod grid; | ||||
| mod origin; | ||||
|  |  | |||
|  | @ -40,7 +40,9 @@ pub unsafe extern "C" fn sp_cp437_grid_new( | |||
|     width: usize, | ||||
|     height: usize, | ||||
| ) -> *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.
 | ||||
|  | @ -67,7 +69,9 @@ pub unsafe extern "C" fn sp_cp437_grid_load( | |||
|     data_length: usize, | ||||
| ) -> *mut SPCp437Grid { | ||||
|     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`.
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter