Skip to content

Commit

Permalink
Merge pull request #28 from rrbutani/add-error-types
Browse files Browse the repository at this point in the history
Use error types instead of `String` throughout the crate
  • Loading branch information
KillingSpark committed Jul 4, 2022
2 parents ebe1506 + 1fcdf13 commit 261e43b
Show file tree
Hide file tree
Showing 20 changed files with 788 additions and 603 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ readme = "Readme.md"
[dependencies]
byteorder = "1.4"
twox-hash = { version = "1.6", default-features = false }
thiserror = "1"

[dev-dependencies]
criterion = "0.3"
Expand Down
1 change: 1 addition & 0 deletions src/blocks/block.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BlockType {
Raw,
RLE,
Expand Down
33 changes: 20 additions & 13 deletions src/blocks/literals_section.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::super::decoding::bit_reader::BitReader;
use super::super::decoding::bit_reader::{BitReader, GetBitsError};

pub struct LiteralsSection {
pub regenerated_size: u32,
Expand All @@ -14,6 +14,17 @@ pub enum LiteralsSectionType {
Treeless,
}

#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum LiteralsSectionParseError {
#[error("Illegal literalssectiontype. Is: {got}, must be in: 0, 1, 2, 3")]
IllegalLiteralSectionType { got: u8 },
#[error(transparent)]
GetBitsError(#[from] GetBitsError),
#[error("Not enough byte to parse the literals section header. Have: {have}, Need: {need}")]
NotEnoughBytes { have: usize, need: u8 },
}

impl std::fmt::Display for LiteralsSectionType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
Expand Down Expand Up @@ -41,7 +52,7 @@ impl LiteralsSection {
}
}

pub fn header_bytes_needed(&self, first_byte: u8) -> Result<u8, String> {
pub fn header_bytes_needed(&self, first_byte: u8) -> Result<u8, LiteralsSectionParseError> {
let ls_type = Self::section_type(first_byte)?;
let size_format = (first_byte >> 2) & 0x3;
match ls_type {
Expand Down Expand Up @@ -91,19 +102,18 @@ impl LiteralsSection {
}
}

pub fn parse_from_header(&mut self, raw: &[u8]) -> Result<u8, String> {
pub fn parse_from_header(&mut self, raw: &[u8]) -> Result<u8, LiteralsSectionParseError> {
let mut br = BitReader::new(raw);
let t = br.get_bits(2)? as u8;
self.ls_type = Self::section_type(t)?;
let size_format = br.get_bits(2)? as u8;

let byte_needed = self.header_bytes_needed(raw[0])?;
if raw.len() < byte_needed as usize {
return Err(format!(
"Not enough byte to parse the literals section header. Have: {}, Want: {}",
raw.len(),
byte_needed
));
return Err(LiteralsSectionParseError::NotEnoughBytes {
have: raw.len(),
need: byte_needed,
});
}

match self.ls_type {
Expand Down Expand Up @@ -200,17 +210,14 @@ impl LiteralsSection {
}
}

fn section_type(raw: u8) -> Result<LiteralsSectionType, String> {
fn section_type(raw: u8) -> Result<LiteralsSectionType, LiteralsSectionParseError> {
let t = raw & 0x3;
match t {
0 => Ok(LiteralsSectionType::Raw),
1 => Ok(LiteralsSectionType::RLE),
2 => Ok(LiteralsSectionType::Compressed),
3 => Ok(LiteralsSectionType::Treeless),
_ => Err(format!(
"Illegal literalssectiontype. Is: {}, must be in: 0,1,2,3",
t
)),
other => Err(LiteralsSectionParseError::IllegalLiteralSectionType { got: other }),
}
}
}
41 changes: 24 additions & 17 deletions src/blocks/sequence_section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ impl Default for SequencesHeader {
}
}

#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SequencesHeaderParseError {
#[error("source must have at least {need_at_least} bytes to parse header; got {} bytes")]
NotEnoughBytes { need_at_least: u8, got: usize },
}

impl SequencesHeader {
pub fn new() -> SequencesHeader {
SequencesHeader {
Expand All @@ -63,13 +70,13 @@ impl SequencesHeader {
}
}

pub fn parse_from_header(&mut self, source: &[u8]) -> Result<u8, String> {
pub fn parse_from_header(&mut self, source: &[u8]) -> Result<u8, SequencesHeaderParseError> {
let mut bytes_read = 0;
if source.is_empty() {
return Err(format!(
"source must have at least {} bytes to parse header",
1
));
return Err(SequencesHeaderParseError::NotEnoughBytes {
need_at_least: 1,
got: 0,
});
}

let source = match source[0] {
Expand All @@ -79,32 +86,32 @@ impl SequencesHeader {
}
1..=127 => {
if source.len() < 2 {
return Err(format!(
"source must have at least {} bytes to parse header",
2
));
return Err(SequencesHeaderParseError::NotEnoughBytes {
need_at_least: 2,
got: source.len(),
});
}
self.num_sequences = u32::from(source[0]);
bytes_read += 1;
&source[1..]
}
128..=254 => {
if source.len() < 3 {
return Err(format!(
"source must have at least {} bytes to parse header",
3
));
return Err(SequencesHeaderParseError::NotEnoughBytes {
need_at_least: 3,
got: source.len(),
});
}
self.num_sequences = ((u32::from(source[0]) - 128) << 8) + u32::from(source[1]);
bytes_read += 2;
&source[2..]
}
255 => {
if source.len() < 4 {
return Err(format!(
"source must have at least {} bytes to parse header",
4
));
return Err(SequencesHeaderParseError::NotEnoughBytes {
need_at_least: 4,
got: source.len(),
});
}
self.num_sequences = u32::from(source[1]) + (u32::from(source[2]) << 8) + 0x7F00;
bytes_read += 3;
Expand Down
28 changes: 21 additions & 7 deletions src/decoding/bit_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ pub struct BitReader<'s> {
source: &'s [u8],
}

#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum GetBitsError {
#[error("Cant serve this request. The reader is limited to {limit} bits, requested {num_requested_bits} bits")]
TooManyBits {
num_requested_bits: usize,
limit: u8,
},
#[error("Can't read {requested} bits, only have {remaining} bits left")]
NotEnoughRemainingBits { requested: usize, remaining: usize },
}

impl<'s> BitReader<'s> {
pub fn new(source: &'s [u8]) -> BitReader<'_> {
BitReader { idx: 0, source }
Expand All @@ -23,16 +35,18 @@ impl<'s> BitReader<'s> {
self.idx -= n;
}

pub fn get_bits(&mut self, n: usize) -> Result<u64, String> {
pub fn get_bits(&mut self, n: usize) -> Result<u64, GetBitsError> {
if n > 64 {
return Err("Cant serve this request. The reader is limited to 64bit".to_owned());
return Err(GetBitsError::TooManyBits {
num_requested_bits: n,
limit: 64,
});
}
if self.bits_left() < n {
return Err(format!(
"Cant read n: {} bits. Bits left: {}",
n,
self.bits_left()
));
return Err(GetBitsError::NotEnoughRemainingBits {
requested: n,
remaining: self.bits_left(),
});
}

let old_idx = self.idx;
Expand Down
19 changes: 14 additions & 5 deletions src/decoding/bit_reader_reverse.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub use super::bit_reader::GetBitsError;
use byteorder::ByteOrder;
use byteorder::LittleEndian;

Expand Down Expand Up @@ -102,7 +103,7 @@ impl<'s> BitReaderReversed<'s> {
}

#[inline(always)]
pub fn get_bits(&mut self, n: u8) -> Result<u64, String> {
pub fn get_bits(&mut self, n: u8) -> Result<u64, GetBitsError> {
if n == 0 {
return Ok(0);
}
Expand All @@ -114,9 +115,12 @@ impl<'s> BitReaderReversed<'s> {
}

#[cold]
fn get_bits_cold(&mut self, n: u8) -> Result<u64, String> {
fn get_bits_cold(&mut self, n: u8) -> Result<u64, GetBitsError> {
if n > 56 {
return Err("Cant serve this request. The reader is limited to 56bit".to_owned());
return Err(GetBitsError::TooManyBits {
num_requested_bits: usize::from(n),
limit: 56,
});
}

let signed_n = n as isize;
Expand Down Expand Up @@ -147,7 +151,12 @@ impl<'s> BitReaderReversed<'s> {
}

#[inline(always)]
pub fn get_bits_triple(&mut self, n1: u8, n2: u8, n3: u8) -> Result<(u64, u64, u64), String> {
pub fn get_bits_triple(
&mut self,
n1: u8,
n2: u8,
n3: u8,
) -> Result<(u64, u64, u64), GetBitsError> {
let sum = n1 as usize + n2 as usize + n3 as usize;
if sum == 0 {
return Ok((0, 0, 0));
Expand Down Expand Up @@ -188,7 +197,7 @@ impl<'s> BitReaderReversed<'s> {
n2: u8,
n3: u8,
sum: u8,
) -> Result<(u64, u64, u64), String> {
) -> Result<(u64, u64, u64), GetBitsError> {
let sum_signed = sum as isize;

if self.bits_remaining() <= 0 {
Expand Down
Loading

0 comments on commit 261e43b

Please sign in to comment.