From 757eab88d67a425728b87286c763387f52367196 Mon Sep 17 00:00:00 2001 From: Genny Date: Mon, 11 Oct 2021 03:36:38 -0500 Subject: Run rustfmt --- src/reader/mod.rs | 526 +++++++++++++++++++++++++++--------------------------- 1 file changed, 263 insertions(+), 263 deletions(-) (limited to 'src/reader') diff --git a/src/reader/mod.rs b/src/reader/mod.rs index 1b52874..7cf1fe1 100644 --- a/src/reader/mod.rs +++ b/src/reader/mod.rs @@ -1,290 +1,290 @@ use std::{ - borrow::Cow, - convert::{TryFrom, TryInto}, - error::Error, - fmt, - fs::File, - io::{BufRead, BufReader, Read}, - path::Path, + borrow::Cow, + convert::{TryFrom, TryInto}, + error::Error, + fmt, + fs::File, + io::{BufRead, BufReader, Read}, + path::Path, }; use crate::{ - block::{ - extension::{Application, Extension, GraphicControl}, - Block, ColorTable, CompressedImage, ImageDescriptor, IndexedImage, ScreenDescriptor, - Version, - }, - color, Gif, + block::{ + extension::{Application, Extension, GraphicControl}, + Block, ColorTable, CompressedImage, ImageDescriptor, IndexedImage, ScreenDescriptor, + Version, + }, + color, Gif, }; pub struct GifReader {} impl GifReader { - pub fn file>(path: P) -> Result { - let mut file = File::open(path)?; - let mut reader = SmartReader { - inner: vec![], - position: 0, - }; - file.read_to_end(&mut reader.inner)?; - - let mut gif = Self::read_required(&mut reader)?; - - if gif.screen_descriptor.color_table_present() { - let gct_size = gif.screen_descriptor.color_table_len() * 3; - gif.global_color_table = Some(Self::read_color_table(&mut reader, gct_size)?); - } - - loop { - match Self::read_block(&mut reader)? { - Some(block) => { - /*match &block { - Block::IndexedImage(_) => println!("Indexed Image"), - Block::BlockedImage(_) => println!("Blocked Image"), - Block::Extension(ext) => match ext { - Extension::GraphicControl(_) => println!("Graphic Cotrol Extension"), - Extension::Looping(_) => println!("Netscape Extension"), - Extension::Comment(vec) => { - println!("Comment Extension {:X}", vec.len()) - } - Extension::Application(_) => todo!(), - }, - }*/ - - gif.blocks.push(block) - } - None => return Ok(gif), - } - } - } - - fn read_required(reader: &mut SmartReader) -> Result { - let version = match reader.take_lossy_utf8(6).as_deref() { - Some("GIF87a") => Version::Gif87a, - Some("GIF89a") => Version::Gif89a, - _ => return Err(DecodingError::UnknownVersionString), - }; - - let mut lsd_buffer: [u8; 7] = [0; 7]; - reader - .read_exact(&mut lsd_buffer) - .ok_or(DecodingError::UnexpectedEof)?; - - let lsd = ScreenDescriptor::from(lsd_buffer); - - Ok(Gif { - header: version, - screen_descriptor: lsd, - global_color_table: None, - blocks: vec![], - }) - } - - fn read_color_table( - reader: &mut SmartReader, - size: usize, - ) -> Result { - let buffer = reader - .take(size as usize) - .ok_or(DecodingError::UnexpectedEof)?; - - // We get the size from the screen descriptor. This should never return Err - Ok(ColorTable::try_from(&buffer[..]).unwrap()) - } - - fn read_block(reader: &mut SmartReader) -> Result, DecodingError> { - let block_id = reader.u8().ok_or(DecodingError::UnexpectedEof)?; - - //TODO: remove panic - match block_id { - 0x21 => Self::read_extension(reader).map(|block| Some(block)), - 0x2C => Self::read_image(reader).map(|block| Some(block)), - 0x3B => Ok(None), - _ => panic!( - "Unknown block identifier {:X} {:X}", - block_id, reader.position - ), - } - } - - fn read_extension(reader: &mut SmartReader) -> Result { - let extension_id = reader.u8().expect("File ended early"); - - match extension_id { - 0xF9 => { - reader.skip(1); // Skip block length, we know it - let mut data = [0u8; 4]; - reader - .read_exact(&mut data) - .ok_or(DecodingError::UnexpectedEof)?; - reader.skip(1); // Skip block terminator - - Ok(Block::Extension(Extension::GraphicControl( - GraphicControl::from(data), - ))) - } - 0xFE => Ok(Block::Extension(Extension::Comment( - reader.take_and_collapse_subblocks(), - ))), - 0x01 => todo!(), //TODO: do; plain text extension - 0xFF => { - //TODO: error instead of unwraps - assert_eq!(Some(11), reader.u8()); - let identifier = reader.take_lossy_utf8(8).unwrap().to_string(); - let authentication_code: [u8; 3] = - TryInto::try_into(reader.take(3).unwrap()).unwrap(); - let data = reader.take_and_collapse_subblocks(); - - Ok(Block::Extension(Extension::Application(Application { - identifier, - authentication_code, - data, - }))) - } - _ => panic!("Unknown Extension Identifier!"), - } - } - - fn read_image(mut reader: &mut SmartReader) -> Result { - let mut buffer = [0u8; 9]; - reader - .read_exact(&mut buffer) - .ok_or(DecodingError::UnexpectedEof)?; - let descriptor = ImageDescriptor::from(buffer); - - let color_table = if descriptor.color_table_present() { - let size = descriptor.color_table_size() * 3; - Some(Self::read_color_table(&mut reader, size)?) - } else { - None - }; - - let lzw_csize = reader.u8().ok_or(DecodingError::UnexpectedEof)?; - - let compressed_data = reader.take_and_collapse_subblocks(); - println!("c{}", compressed_data.len()); - - let mut decompress = weezl::decode::Decoder::new(weezl::BitOrder::Lsb, lzw_csize); - //TODO: remove unwrap - let mut decompressed_data = decompress.decode(&compressed_data).unwrap(); - - Ok(Block::IndexedImage(IndexedImage { - image_descriptor: descriptor, - local_color_table: color_table, - indicies: decompressed_data, - })) - } + pub fn file>(path: P) -> Result { + let mut file = File::open(path)?; + let mut reader = SmartReader { + inner: vec![], + position: 0, + }; + file.read_to_end(&mut reader.inner)?; + + let mut gif = Self::read_required(&mut reader)?; + + if gif.screen_descriptor.color_table_present() { + let gct_size = gif.screen_descriptor.color_table_len() * 3; + gif.global_color_table = Some(Self::read_color_table(&mut reader, gct_size)?); + } + + loop { + match Self::read_block(&mut reader)? { + Some(block) => { + /*match &block { + Block::IndexedImage(_) => println!("Indexed Image"), + Block::BlockedImage(_) => println!("Blocked Image"), + Block::Extension(ext) => match ext { + Extension::GraphicControl(_) => println!("Graphic Cotrol Extension"), + Extension::Looping(_) => println!("Netscape Extension"), + Extension::Comment(vec) => { + println!("Comment Extension {:X}", vec.len()) + } + Extension::Application(_) => todo!(), + }, + }*/ + + gif.blocks.push(block) + } + None => return Ok(gif), + } + } + } + + fn read_required(reader: &mut SmartReader) -> Result { + let version = match reader.take_lossy_utf8(6).as_deref() { + Some("GIF87a") => Version::Gif87a, + Some("GIF89a") => Version::Gif89a, + _ => return Err(DecodingError::UnknownVersionString), + }; + + let mut lsd_buffer: [u8; 7] = [0; 7]; + reader + .read_exact(&mut lsd_buffer) + .ok_or(DecodingError::UnexpectedEof)?; + + let lsd = ScreenDescriptor::from(lsd_buffer); + + Ok(Gif { + header: version, + screen_descriptor: lsd, + global_color_table: None, + blocks: vec![], + }) + } + + fn read_color_table( + reader: &mut SmartReader, + size: usize, + ) -> Result { + let buffer = reader + .take(size as usize) + .ok_or(DecodingError::UnexpectedEof)?; + + // We get the size from the screen descriptor. This should never return Err + Ok(ColorTable::try_from(&buffer[..]).unwrap()) + } + + fn read_block(reader: &mut SmartReader) -> Result, DecodingError> { + let block_id = reader.u8().ok_or(DecodingError::UnexpectedEof)?; + + //TODO: remove panic + match block_id { + 0x21 => Self::read_extension(reader).map(|block| Some(block)), + 0x2C => Self::read_image(reader).map(|block| Some(block)), + 0x3B => Ok(None), + _ => panic!( + "Unknown block identifier {:X} {:X}", + block_id, reader.position + ), + } + } + + fn read_extension(reader: &mut SmartReader) -> Result { + let extension_id = reader.u8().expect("File ended early"); + + match extension_id { + 0xF9 => { + reader.skip(1); // Skip block length, we know it + let mut data = [0u8; 4]; + reader + .read_exact(&mut data) + .ok_or(DecodingError::UnexpectedEof)?; + reader.skip(1); // Skip block terminator + + Ok(Block::Extension(Extension::GraphicControl( + GraphicControl::from(data), + ))) + } + 0xFE => Ok(Block::Extension(Extension::Comment( + reader.take_and_collapse_subblocks(), + ))), + 0x01 => todo!(), //TODO: do; plain text extension + 0xFF => { + //TODO: error instead of unwraps + assert_eq!(Some(11), reader.u8()); + let identifier = reader.take_lossy_utf8(8).unwrap().to_string(); + let authentication_code: [u8; 3] = + TryInto::try_into(reader.take(3).unwrap()).unwrap(); + let data = reader.take_and_collapse_subblocks(); + + Ok(Block::Extension(Extension::Application(Application { + identifier, + authentication_code, + data, + }))) + } + _ => panic!("Unknown Extension Identifier!"), + } + } + + fn read_image(mut reader: &mut SmartReader) -> Result { + let mut buffer = [0u8; 9]; + reader + .read_exact(&mut buffer) + .ok_or(DecodingError::UnexpectedEof)?; + let descriptor = ImageDescriptor::from(buffer); + + let color_table = if descriptor.color_table_present() { + let size = descriptor.color_table_size() * 3; + Some(Self::read_color_table(&mut reader, size)?) + } else { + None + }; + + let lzw_csize = reader.u8().ok_or(DecodingError::UnexpectedEof)?; + + let compressed_data = reader.take_and_collapse_subblocks(); + println!("c{}", compressed_data.len()); + + let mut decompress = weezl::decode::Decoder::new(weezl::BitOrder::Lsb, lzw_csize); + //TODO: remove unwrap + let mut decompressed_data = decompress.decode(&compressed_data).unwrap(); + + Ok(Block::IndexedImage(IndexedImage { + image_descriptor: descriptor, + local_color_table: color_table, + indicies: decompressed_data, + })) + } } #[derive(Debug)] pub enum DecodingError { - IoError(std::io::Error), - UnknownVersionString, - UnexpectedEof, - ColorIndexOutOfBounds, + IoError(std::io::Error), + UnknownVersionString, + UnexpectedEof, + ColorIndexOutOfBounds, } impl Error for DecodingError {} impl fmt::Display for DecodingError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DecodingError::IoError(error) => write!(f, "{}", error), - DecodingError::UnknownVersionString => { - write!(f, "File did not start with a valid header") - } - DecodingError::UnexpectedEof => { - write!(f, "Found the end of the data at a weird spot") - } - DecodingError::ColorIndexOutOfBounds => { - write!( - f, - "The image contained an index not found in the color table" - ) - } - } - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + DecodingError::IoError(error) => write!(f, "{}", error), + DecodingError::UnknownVersionString => { + write!(f, "File did not start with a valid header") + } + DecodingError::UnexpectedEof => { + write!(f, "Found the end of the data at a weird spot") + } + DecodingError::ColorIndexOutOfBounds => { + write!( + f, + "The image contained an index not found in the color table" + ) + } + } + } } impl From for DecodingError { - fn from(ioerror: std::io::Error) -> Self { - DecodingError::IoError(ioerror) - } + fn from(ioerror: std::io::Error) -> Self { + DecodingError::IoError(ioerror) + } } struct SmartReader { - inner: Vec, - position: usize, + inner: Vec, + position: usize, } impl SmartReader { - pub fn u8(&mut self) -> Option { - self.position += 1; - self.inner.get(self.position - 1).map(|b| *b) - } - - pub fn u16(&mut self) -> Option { - self.position += 2; - self.inner - .get(self.position - 2..self.position) - .map(|bytes| u16::from_le_bytes(bytes.try_into().unwrap())) - } - - pub fn skip(&mut self, size: usize) { - self.position += size; - } - - pub fn take(&mut self, size: usize) -> Option<&[u8]> { - self.position += size; - self.inner.get(self.position - size..self.position) - } - - //TODO: Result not Option when buffer len - pub fn read_exact(&mut self, buf: &mut [u8]) -> Option<()> { - if self.position + buf.len() > self.inner.len() { - None - } else { - self.position += buf.len(); - buf.copy_from_slice(&self.inner[self.position - buf.len()..self.position]); - Some(()) - } - } - - pub fn take_vec(&mut self, size: usize) -> Option> { - self.position += size; - self.inner - .get(self.position - size..self.position) - .map(|bytes| bytes.to_vec()) - } - - pub fn take_lossy_utf8(&mut self, size: usize) -> Option> { - self.take(size).map(|bytes| String::from_utf8_lossy(bytes)) - } - - pub fn take_data_subblocks(&mut self) -> Vec> { - let mut blocks = vec![]; - - loop { - let block_size = self.u8().expect("Failed to read length of sublock"); - - if block_size == 0 { - return blocks; - } - - let block = self - .take_vec(block_size as usize) - .expect("Failed to read sublock"); - - blocks.push(block); - } - } - - pub fn take_and_collapse_subblocks(&mut self) -> Vec { - let blocks = self.take_data_subblocks(); - let mut ret = vec![]; - for block in blocks { - ret.extend_from_slice(&block) - } - - ret - } + pub fn u8(&mut self) -> Option { + self.position += 1; + self.inner.get(self.position - 1).map(|b| *b) + } + + pub fn u16(&mut self) -> Option { + self.position += 2; + self.inner + .get(self.position - 2..self.position) + .map(|bytes| u16::from_le_bytes(bytes.try_into().unwrap())) + } + + pub fn skip(&mut self, size: usize) { + self.position += size; + } + + pub fn take(&mut self, size: usize) -> Option<&[u8]> { + self.position += size; + self.inner.get(self.position - size..self.position) + } + + //TODO: Result not Option when buffer len + pub fn read_exact(&mut self, buf: &mut [u8]) -> Option<()> { + if self.position + buf.len() > self.inner.len() { + None + } else { + self.position += buf.len(); + buf.copy_from_slice(&self.inner[self.position - buf.len()..self.position]); + Some(()) + } + } + + pub fn take_vec(&mut self, size: usize) -> Option> { + self.position += size; + self.inner + .get(self.position - size..self.position) + .map(|bytes| bytes.to_vec()) + } + + pub fn take_lossy_utf8(&mut self, size: usize) -> Option> { + self.take(size).map(|bytes| String::from_utf8_lossy(bytes)) + } + + pub fn take_data_subblocks(&mut self) -> Vec> { + let mut blocks = vec![]; + + loop { + let block_size = self.u8().expect("Failed to read length of sublock"); + + if block_size == 0 { + return blocks; + } + + let block = self + .take_vec(block_size as usize) + .expect("Failed to read sublock"); + + blocks.push(block); + } + } + + pub fn take_and_collapse_subblocks(&mut self) -> Vec { + let blocks = self.take_data_subblocks(); + let mut ret = vec![]; + for block in blocks { + ret.extend_from_slice(&block) + } + + ret + } } -- cgit 1.4.1-3-g733a5