Chapter 2 Hints
Getting bytes from a string
You can turn a &str
into a Vec<u8>
using str::bytes.
let bytes: Vec<u8> = your_str.bytes().collect();
Getting a string from bytes
You can turn a Vec<u8>
into a String
using String::from_utf8.
Working with iterators
You can chain iterators together using Iterator::chain.
You might run into trouble getting the types of your iterators to match. You can use Iterator::copied or Iterator::cloned to ensure that your iterator is working with values rather than references.
#![allow(unused_variables)] fn main() { let result = first_collection .iter() .cloned() .chain(second_collection.iter().cloned()) .chain(third_collection.iter().cloned()) .collect(); }
Reading bytes
You can turn a [u8; 4]
into a u32
with u32::from_be_bytes. The be
stands for big endian.
You can read a fixed number of bytes from a reader using Read::read_exact. Chunks have several different 4-byte sequences.
#![allow(unused_variables)] fn main() { let mut reader = BufReader::new(bytes); let mut buffer: [u8; 4] = [0, 0, 0, 0]; reader.read_exact(&mut buffer)?; let data_length = u32::from_be_bytes(buffer); }
Stubs
#![allow(unused_variables)] fn main() { use std::convert::TryFrom; use std::fmt; use std::io::{BufReader, Read}; use crate::{Error, Result}; use crate::png::ChunkType; /// A validated PNG chunk. See the PNG Spec for more details /// http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html #[derive(Debug, Clone)] pub struct Chunk { // Write me! } impl Chunk { /// The length of the data portion of this chunk. pub fn length(&self) -> u32 { todo!() } /// The `ChunkType` of this chunk pub fn chunk_type(&self) -> &ChunkType { todo!() } /// The raw data contained in this chunk in bytes pub fn data(&self) -> &[u8] { todo!() } /// The CRC of this chunk pub fn crc(&self) -> u32 { todo!() } /// Returns the data stored in this chunk as a `String`. This function will return an error /// if the stored data is not valid UTF-8. pub fn data_as_string(&self) -> Result<String> { todo!() } /// Returns this chunk as a byte sequences described by the PNG spec. /// The following data is included in this byte sequence in order: /// 1. Length of the data *(4 bytes)* /// 2. Chunk type *(4 bytes)* /// 3. The data itself *(`length` bytes)* /// 4. The CRC of the chunk type and data *(4 bytes)* pub fn as_bytes(&self) -> Vec<u8> { todo!() } } impl TryFrom<&[u8]> for Chunk { type Error = Error; fn try_from(bytes: &[u8]) -> Result<Self> { todo!() } } impl fmt::Display for Chunk { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "Chunk {{",)?; writeln!(f, " Length: {}", self.length())?; writeln!(f, " Type: {}", self.chunk_type())?; writeln!(f, " Data: {} bytes", self.data().len())?; writeln!(f, " Crc: {}", self.crc())?; writeln!(f, "}}",)?; Ok(()) } } }