add gz compression
This commit is contained in:
		
							parent
							
								
									0e393896d3
								
							
						
					
					
						commit
						5c61d02749
					
				
					 8 changed files with 243 additions and 108 deletions
				
			
		
							
								
								
									
										41
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										41
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -2,18 +2,58 @@ | |||
| # It is not intended for manual editing. | ||||
| version = 3 | ||||
| 
 | ||||
| [[package]] | ||||
| name = "adler" | ||||
| version = "1.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "autocfg" | ||||
| version = "1.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cfg-if" | ||||
| version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "crc32fast" | ||||
| version = "1.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "flate2" | ||||
| version = "1.0.30" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" | ||||
| dependencies = [ | ||||
|  "crc32fast", | ||||
|  "miniz_oxide", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "log" | ||||
| version = "0.4.21" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "miniz_oxide" | ||||
| version = "0.7.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" | ||||
| dependencies = [ | ||||
|  "adler", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "num" | ||||
| version = "0.4.3" | ||||
|  | @ -120,6 +160,7 @@ dependencies = [ | |||
| name = "servicepoint2" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "flate2", | ||||
|  "log", | ||||
|  "num", | ||||
|  "num-derive", | ||||
|  |  | |||
|  | @ -7,4 +7,5 @@ edition = "2021" | |||
| num = "0.4" | ||||
| num-derive = "0.4" | ||||
| num-traits = "0.2" | ||||
| log = "0.4.21" | ||||
| log = "0.4" | ||||
| flate2 = "1.0" | ||||
|  |  | |||
							
								
								
									
										35
									
								
								examples/Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										35
									
								
								examples/Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -2,6 +2,12 @@ | |||
| # It is not intended for manual editing. | ||||
| version = 3 | ||||
| 
 | ||||
| [[package]] | ||||
| name = "adler" | ||||
| version = "1.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "aho-corasick" | ||||
| version = "1.1.3" | ||||
|  | @ -128,6 +134,15 @@ version = "1.0.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "crc32fast" | ||||
| version = "1.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "env_filter" | ||||
| version = "0.1.0" | ||||
|  | @ -151,6 +166,16 @@ dependencies = [ | |||
|  "log", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "flate2" | ||||
| version = "1.0.30" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" | ||||
| dependencies = [ | ||||
|  "crc32fast", | ||||
|  "miniz_oxide", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "game_of_life" | ||||
| version = "0.1.0" | ||||
|  | @ -209,6 +234,15 @@ version = "2.7.2" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "miniz_oxide" | ||||
| version = "0.7.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" | ||||
| dependencies = [ | ||||
|  "adler", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "moving_line" | ||||
| version = "0.1.0" | ||||
|  | @ -401,6 +435,7 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" | |||
| name = "servicepoint2" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "flate2", | ||||
|  "log", | ||||
|  "num", | ||||
|  "num-derive", | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ use std::time::Duration; | |||
| 
 | ||||
| use clap::Parser; | ||||
| 
 | ||||
| use servicepoint2::{BitVec, Connection, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid}; | ||||
| use servicepoint2::{BitVec, CompressionCode, Connection, PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid}; | ||||
| use servicepoint2::Command::BitmapLinearAnd; | ||||
| 
 | ||||
| #[derive(Parser, Debug)] | ||||
|  | @ -16,7 +16,7 @@ struct Cli { | |||
| 
 | ||||
| fn main() { | ||||
|     env_logger::builder() | ||||
|         .filter_level(log::LevelFilter::Info) | ||||
|         .filter_level(log::LevelFilter::Debug) | ||||
|         .init(); | ||||
|     let cli = Cli::parse(); | ||||
| 
 | ||||
|  | @ -35,7 +35,7 @@ fn main() { | |||
|         let pixel_data: Vec<u8> = enabled_pixels.clone().into(); | ||||
|         let bit_vec = BitVec::load(&*pixel_data); | ||||
| 
 | ||||
|         connection.send(BitmapLinearAnd(0, bit_vec)).unwrap(); | ||||
|         connection.send(BitmapLinearAnd(0, bit_vec, CompressionCode::Gz)).unwrap(); | ||||
|         thread::sleep(sleep_duration); | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										238
									
								
								src/command.rs
									
										
									
									
									
								
							
							
						
						
									
										238
									
								
								src/command.rs
									
										
									
									
									
								
							|  | @ -1,5 +1,9 @@ | |||
| use std::io::Read; | ||||
| use flate2::bufread::GzEncoder; | ||||
| use flate2::Compression; | ||||
| use flate2::read::GzDecoder; | ||||
| use crate::{BitVec, ByteGrid, Header, Packet, PixelGrid, TILE_SIZE}; | ||||
| use crate::command_codes::CommandCode; | ||||
| use crate::command_codes::{CommandCode, CompressionCode}; | ||||
| 
 | ||||
| /// An origin marks the top left position of the
 | ||||
| /// data sent to the display.
 | ||||
|  | @ -29,28 +33,14 @@ pub enum Command { | |||
|     Brightness(Brightness), | ||||
|     #[deprecated] | ||||
|     BitmapLegacy, | ||||
|     BitmapLinear(Offset, BitVec), | ||||
|     BitmapLinearAnd(Offset, BitVec), | ||||
|     BitmapLinearOr(Offset, BitVec), | ||||
|     BitmapLinearXor(Offset, BitVec), | ||||
|     BitmapLinear(Offset, BitVec, CompressionCode), | ||||
|     BitmapLinearAnd(Offset, BitVec, CompressionCode), | ||||
|     BitmapLinearOr(Offset, BitVec, CompressionCode), | ||||
|     BitmapLinearXor(Offset, BitVec, CompressionCode), | ||||
|     Cp437Data(Origin, ByteGrid), | ||||
|     BitmapLinearWin(Origin, PixelGrid), | ||||
| } | ||||
| 
 | ||||
| fn offset_and_payload(command: CommandCode, offset: Offset, payload: Vec<u8>) -> Packet { | ||||
|     Packet(Header(command.to_primitive(), offset, payload.len() as u16, 0, 0), payload) | ||||
| } | ||||
| 
 | ||||
| fn origin_size_payload(command: CommandCode, origin: Origin, size: Size, payload: Vec<u8>) -> Packet { | ||||
|     let Origin(x, y) = origin; | ||||
|     let Size(w, h) = size; | ||||
|     Packet(Header(command.to_primitive(), x, y, w, h), payload.into()) | ||||
| } | ||||
| 
 | ||||
| fn command_code_only(code: CommandCode) -> Packet { | ||||
|     Packet(Header(code.to_primitive(), 0x0000, 0x0000, 0x0000, 0x0000), vec!()) | ||||
| } | ||||
| 
 | ||||
| impl Into<Packet> for Command { | ||||
|     fn into(self) -> Packet { | ||||
|         match self { | ||||
|  | @ -59,7 +49,6 @@ impl Into<Packet> for Command { | |||
|             Command::HardReset => command_code_only(CommandCode::HardReset), | ||||
|             #[allow(deprecated)] | ||||
|             Command::BitmapLegacy => command_code_only(CommandCode::BitmapLegacy), | ||||
| 
 | ||||
|             Command::CharBrightness(origin, grid) => { | ||||
|                 origin_size_payload(CommandCode::CharBrightness, | ||||
|                                     origin, | ||||
|  | @ -69,10 +58,6 @@ impl Into<Packet> for Command { | |||
|             Command::Brightness(brightness) => { | ||||
|                 Packet(Header(CommandCode::Brightness.to_primitive(), 0x00000, 0x0000, 0x0000, 0x0000), vec!(brightness)) | ||||
|             } | ||||
| 
 | ||||
|             Command::BitmapLinear(offset, bits) => { | ||||
|                 offset_and_payload(CommandCode::BitmapLinear, offset, bits.into()) | ||||
|             } | ||||
|             Command::BitmapLinearWin(Origin(pixel_x, pixel_y), pixels) => { | ||||
|                 debug_assert_eq!(pixel_x % 8, 0); | ||||
|                 debug_assert_eq!(pixels.width % 8, 0); | ||||
|  | @ -84,14 +69,17 @@ impl Into<Packet> for Command { | |||
|                            pixels.height as u16), | ||||
|                     pixels.into()) | ||||
|             } | ||||
|             Command::BitmapLinearAnd(offset, bits) => { | ||||
|                 offset_and_payload(CommandCode::BitmapLinearAnd, offset, bits.into()) | ||||
|             Command::BitmapLinear(offset, bits, compression) => { | ||||
|                 bitmap_linear_into_packet(CommandCode::BitmapLinear, offset, compression, bits.into()) | ||||
|             } | ||||
|             Command::BitmapLinearOr(offset, bits) => { | ||||
|                 offset_and_payload(CommandCode::BitmapLinearOr, offset, bits.into()) | ||||
|             Command::BitmapLinearAnd(offset, bits, compression) => { | ||||
|                 bitmap_linear_into_packet(CommandCode::BitmapLinearAnd, offset, compression, bits.into()) | ||||
|             } | ||||
|             Command::BitmapLinearXor(offset, bits) => { | ||||
|                 offset_and_payload(CommandCode::BitmapLinearXor, offset, bits.into()) | ||||
|             Command::BitmapLinearOr(offset, bits, compression) => { | ||||
|                 bitmap_linear_into_packet(CommandCode::BitmapLinearOr, offset, compression, bits.into()) | ||||
|             } | ||||
|             Command::BitmapLinearXor(offset, bits, compression) => { | ||||
|                 bitmap_linear_into_packet(CommandCode::BitmapLinearXor, offset, compression, bits.into()) | ||||
|             } | ||||
|             Command::Cp437Data(origin, grid) => { | ||||
|                 origin_size_payload(CommandCode::Cp437Data, | ||||
|  | @ -108,86 +96,62 @@ pub enum TryFromPacketError { | |||
|     InvalidCommand(u16), | ||||
|     UnexpectedPayloadSize(usize, usize), | ||||
|     ExtraneousHeaderValues, | ||||
|     UnsupportedSubcommand(u16), | ||||
| } | ||||
| 
 | ||||
| fn check_empty_header(packet: &Packet) -> Option<TryFromPacketError> { | ||||
|     let Packet(Header(_, a, b, c, d), _) = &packet; | ||||
|     if *a != 0 || *b != 0 || *c != 0 || *d != 0 { | ||||
|         Some(TryFromPacketError::ExtraneousHeaderValues) | ||||
|     } else { | ||||
|         None | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn check_command_only(packet: &Packet) -> Option<TryFromPacketError> { | ||||
|     let Packet(_, payload) = packet; | ||||
|     if payload.len() != 0 { | ||||
|         Some(TryFromPacketError::UnexpectedPayloadSize(0, payload.len())) | ||||
|     } else { | ||||
|         check_empty_header(packet) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn check_linear_bitmap(packet: &Packet) -> Option<TryFromPacketError> { | ||||
|     let Packet(Header(_, _, length, sub, reserved), payload) = packet; | ||||
|     if *reserved != 0 { | ||||
|         return Some(TryFromPacketError::ExtraneousHeaderValues); | ||||
|     } | ||||
|     if *sub != 0 { | ||||
|         return Some(TryFromPacketError::UnsupportedSubcommand(*sub)); | ||||
|     } | ||||
|     if payload.len() != *length as usize { | ||||
|         return Some(TryFromPacketError::UnexpectedPayloadSize(*length as usize, payload.len())); | ||||
|     } | ||||
|     None | ||||
|     InvalidCompressionCode(u16), | ||||
|     DecompressionFailed(std::io::Error), | ||||
| } | ||||
| 
 | ||||
| impl TryFrom<Packet> for Command { | ||||
|     type Error = TryFromPacketError; | ||||
| 
 | ||||
|     fn try_from(value: Packet) -> Result<Self, Self::Error> { | ||||
|         let Packet(Header(command_u16, a, b, c, d), payload) = &value; | ||||
|         let command_code = match CommandCode::from_primitive(*command_u16) { | ||||
|             None => return Err(TryFromPacketError::InvalidCommand(*command_u16)), | ||||
|         let Packet(Header(command_u16, a, b, c, d), _) = value; | ||||
|         let command_code = match CommandCode::from_primitive(command_u16) { | ||||
|             None => return Err(TryFromPacketError::InvalidCommand(command_u16)), | ||||
|             Some(value) => value | ||||
|         }; | ||||
| 
 | ||||
|         match command_code { | ||||
|             CommandCode::Clear => { | ||||
|                 if let Some(err) = check_command_only(&value) { | ||||
|                     return Err(err); | ||||
|                 match check_command_only(value) { | ||||
|                     Some(err) => Err(err), | ||||
|                     None => Ok(Command::Clear), | ||||
|                 } | ||||
|                 Ok(Command::Clear) | ||||
|             } | ||||
|             CommandCode::Brightness => { | ||||
|                 if let Some(err) = check_empty_header(&value) { | ||||
|                     return Err(err); | ||||
|                 let Packet(header, payload) = value; | ||||
|                 if payload.len() != 1 { | ||||
|                     return Err(TryFromPacketError::UnexpectedPayloadSize(1, payload.len())); | ||||
|                 } | ||||
| 
 | ||||
|                 match check_empty_header(header) { | ||||
|                     Some(err) => Err(err), | ||||
|                     None => Ok(Command::Brightness(payload[0])), | ||||
|                 } | ||||
|                 Ok(Command::Brightness(payload[0])) | ||||
|             } | ||||
|             CommandCode::HardReset => { | ||||
|                 if let Some(err) = check_command_only(&value) { | ||||
|                     return Err(err); | ||||
|                 match check_command_only(value) { | ||||
|                     Some(err) => Err(err), | ||||
|                     None => Ok(Command::HardReset), | ||||
|                 } | ||||
|                 Ok(Command::HardReset) | ||||
|             } | ||||
|             CommandCode::FadeOut => { | ||||
|                 if let Some(err) = check_command_only(&value) { | ||||
|                     return Err(err); | ||||
|                 match check_command_only(value) { | ||||
|                     Some(err) => Err(err), | ||||
|                     None => Ok(Command::FadeOut), | ||||
|                 } | ||||
|                 Ok(Command::FadeOut) | ||||
|             } | ||||
|             CommandCode::Cp437Data => { | ||||
|                 let Packet(_, payload) = value; | ||||
|                 Ok(Command::Cp437Data( | ||||
|                     Origin(*a, *b), | ||||
|                     ByteGrid::load(*c as usize, *d as usize, payload), | ||||
|                     Origin(a, b), | ||||
|                     ByteGrid::load(c as usize, d as usize, &payload), | ||||
|                 )) | ||||
|             } | ||||
|             CommandCode::CharBrightness => { | ||||
|                 let Packet(_, payload) = value; | ||||
|                 Ok(Command::CharBrightness( | ||||
|                     Origin(*a, *b), | ||||
|                     ByteGrid::load(*c as usize, *d as usize, payload), | ||||
|                     Origin(a, b), | ||||
|                     ByteGrid::load(c as usize, d as usize, &payload), | ||||
|                 )) | ||||
|             } | ||||
|             #[allow(deprecated)] | ||||
|  | @ -195,35 +159,109 @@ impl TryFrom<Packet> for Command { | |||
|                 Ok(Command::BitmapLegacy) | ||||
|             } | ||||
|             CommandCode::BitmapLinearWin => { | ||||
|                 let Packet(_, payload) = value; | ||||
|                 Ok(Command::BitmapLinearWin( | ||||
|                     Origin(*a * TILE_SIZE, *b), | ||||
|                     PixelGrid::load(*c as usize * TILE_SIZE as usize, *d as usize, payload), | ||||
|                     Origin(a * TILE_SIZE, b), | ||||
|                     PixelGrid::load(c as usize * TILE_SIZE as usize, d as usize, &payload), | ||||
|                 )) | ||||
|             } | ||||
|             CommandCode::BitmapLinear => { | ||||
|                 if let Some(err) = check_linear_bitmap(&value) { | ||||
|                     return Err(err); | ||||
|                 } | ||||
|                 Ok(Command::BitmapLinear(*a, BitVec::load(payload))) | ||||
|                 let (vec, compression) = packet_into_linear_bitmap(value)?; | ||||
|                 Ok(Command::BitmapLinear(a, vec, compression)) | ||||
|             } | ||||
|             CommandCode::BitmapLinearAnd => { | ||||
|                 if let Some(err) = check_linear_bitmap(&value) { | ||||
|                     return Err(err); | ||||
|                 } | ||||
|                 Ok(Command::BitmapLinearAnd(*a, BitVec::load(payload))) | ||||
|                 let (vec, compression) = packet_into_linear_bitmap(value)?; | ||||
|                 Ok(Command::BitmapLinearAnd(a, vec, compression)) | ||||
|             } | ||||
|             CommandCode::BitmapLinearOr => { | ||||
|                 if let Some(err) = check_linear_bitmap(&value) { | ||||
|                     return Err(err); | ||||
|                 } | ||||
|                 Ok(Command::BitmapLinearOr(*a, BitVec::load(payload))) | ||||
|                 let (vec, compression) = packet_into_linear_bitmap(value)?; | ||||
|                 Ok(Command::BitmapLinearOr(a, vec, compression)) | ||||
|             } | ||||
|             CommandCode::BitmapLinearXor => { | ||||
|                 if let Some(err) = check_linear_bitmap(&value) { | ||||
|                     return Err(err); | ||||
|                 } | ||||
|                 Ok(Command::BitmapLinearXor(*a, BitVec::load(payload))) | ||||
|                 let (vec, compression) = packet_into_linear_bitmap(value)?; | ||||
|                 Ok(Command::BitmapLinearXor(a, vec, compression)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn bitmap_linear_into_packet(command: CommandCode, offset: Offset, compression: CompressionCode, payload: Vec<u8>) -> Packet { | ||||
|     let payload = match compression { | ||||
|         CompressionCode::None => payload, | ||||
|         CompressionCode::Gz => { | ||||
|             let mut encoder = GzEncoder::new(&*payload, Compression::best()); | ||||
|             let mut compressed = vec!(); | ||||
|             match encoder.read_to_end(&mut compressed) { | ||||
|                 Err(err) => panic!("could not compress payload: {}", err), | ||||
|                 Ok(_) => compressed, | ||||
|             } | ||||
|         } | ||||
|         CompressionCode::Bz => todo!(), | ||||
|         CompressionCode::Lz => todo!(), | ||||
|         CompressionCode::Zs => todo!(), | ||||
|     }; | ||||
| 
 | ||||
|     let compression = CompressionCode::to_primitive(&compression); | ||||
|     Packet(Header(command.to_primitive(), offset, payload.len() as u16, compression, 0), payload) | ||||
| } | ||||
| 
 | ||||
| fn origin_size_payload(command: CommandCode, origin: Origin, size: Size, payload: Vec<u8>) -> Packet { | ||||
|     let Origin(x, y) = origin; | ||||
|     let Size(w, h) = size; | ||||
|     Packet(Header(command.to_primitive(), x, y, w, h), payload.into()) | ||||
| } | ||||
| 
 | ||||
| fn command_code_only(code: CommandCode) -> Packet { | ||||
|     Packet(Header(code.to_primitive(), 0x0000, 0x0000, 0x0000, 0x0000), vec!()) | ||||
| } | ||||
| 
 | ||||
| fn check_empty_header(header: Header) -> Option<TryFromPacketError> { | ||||
|     let Header(_, a, b, c, d) = header; | ||||
|     if a != 0 || b != 0 || c != 0 || d != 0 { | ||||
|         Some(TryFromPacketError::ExtraneousHeaderValues) | ||||
|     } else { | ||||
|         None | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn check_command_only(packet: Packet) -> Option<TryFromPacketError> { | ||||
|     let Packet(Header(_, a, b, c, d), payload) = packet; | ||||
|     if payload.len() != 0 { | ||||
|         Some(TryFromPacketError::UnexpectedPayloadSize(0, payload.len())) | ||||
|     } else if a != 0 || b != 0 || c != 0 || d != 0 { | ||||
|         Some(TryFromPacketError::ExtraneousHeaderValues) | ||||
|     } else { | ||||
|         None | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn packet_into_linear_bitmap(packet: Packet) -> Result<(BitVec, CompressionCode), TryFromPacketError> { | ||||
|     let Packet(Header(_, _, length, sub, reserved), payload) = packet; | ||||
|     if reserved != 0 { | ||||
|         return Err(TryFromPacketError::ExtraneousHeaderValues); | ||||
|     } | ||||
|     if payload.len() != length as usize { | ||||
|         return Err(TryFromPacketError::UnexpectedPayloadSize(length as usize, payload.len())); | ||||
|     } | ||||
|     let sub = match CompressionCode::from_primitive(sub) { | ||||
|         None => return Err(TryFromPacketError::InvalidCompressionCode(sub)), | ||||
|         Some(value) => value | ||||
|     }; | ||||
|     let payload = match sub { | ||||
|         CompressionCode::None => payload, | ||||
|         CompressionCode::Gz => { | ||||
|             let mut decoder = GzDecoder::new(&*payload); | ||||
|             let mut decompressed = vec!(); | ||||
|             match decoder.read_to_end(&mut decompressed) { | ||||
|                 Err(err) => return Err(TryFromPacketError::DecompressionFailed(err)), | ||||
|                 Ok(_) => {} | ||||
|             } | ||||
|             decompressed | ||||
|         } | ||||
|         CompressionCode::Bz => todo!(), | ||||
|         CompressionCode::Lz => todo!(), | ||||
|         CompressionCode::Zs => todo!(), | ||||
|     }; | ||||
| 
 | ||||
|     Ok((BitVec::load(&payload), sub)) | ||||
| } | ||||
|  |  | |||
|  | @ -27,4 +27,24 @@ impl CommandCode { | |||
|     pub fn to_primitive(&self) -> u16 { | ||||
|         ToPrimitive::to_u16(self).unwrap() | ||||
|     } | ||||
| } | ||||
| } | ||||
| 
 | ||||
| #[repr(u16)] | ||||
| #[derive(Debug, FromPrimitive, ToPrimitive)] | ||||
| pub enum CompressionCode { | ||||
|     None = 0x0, | ||||
|     Gz = 0x677a, | ||||
|     Bz = 0x627a, | ||||
|     Lz = 0x6c7a, | ||||
|     Zs = 0x7a73, | ||||
| } | ||||
| 
 | ||||
| impl CompressionCode { | ||||
|     pub fn from_primitive(value: u16) -> Option<Self> { | ||||
|         FromPrimitive::from_u16(value) | ||||
|     } | ||||
| 
 | ||||
|     pub fn to_primitive(&self) -> u16 { | ||||
|         ToPrimitive::to_u16(self).unwrap() | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -17,9 +17,9 @@ impl Connection { | |||
|     } | ||||
| 
 | ||||
|     /// Send a command to the display
 | ||||
|     pub fn send(&self, packet: impl Into<Packet> + Debug) -> std::io::Result<()> { | ||||
|     pub fn send(&self, packet: impl Into<Packet> + Debug) -> Result<(), std::io::Error> { | ||||
|         debug!("sending {packet:?}"); | ||||
|         let packet = packet.into(); | ||||
|         let packet: Packet = packet.into(); | ||||
|         let data: Vec<u8> = packet.into(); | ||||
|         self.socket.send(&*data)?; | ||||
|         Ok(()) | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ pub use crate::pixel_grid::PixelGrid; | |||
| pub use crate::bit_vec::BitVec; | ||||
| pub use crate::packet::{Packet, Header, Payload}; | ||||
| pub use crate::command::{Command, Size, Origin}; | ||||
| pub use crate::command_codes::CommandCode; | ||||
| pub use crate::command_codes::{CommandCode, CompressionCode}; | ||||
| pub use crate::byte_grid::ByteGrid; | ||||
| 
 | ||||
| pub const TILE_SIZE: u16 = 8; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter