Skip to content

Commit 2eb7a30

Browse files
author
David James
committed
fix: rewrite process_segment to fix #15
Recursion Versus Iteration: Debate Amongst Yourselves
1 parent 41b2b6a commit 2eb7a30

File tree

2 files changed

+27
-25
lines changed

2 files changed

+27
-25
lines changed

src/utility.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,14 @@ impl<I: Read + Write + Seek> CrcStore<I> {
4242
self.inner_pos += i as u64;
4343
Ok(i)
4444
}
45+
46+
/// Reads up to `n` bytes from the `inner` I/O object using the
47+
/// pre-allocated `self.buf` buffer. Updates the `hasher` accordingly.
48+
/// Returns the checksum from the last 4 bytes read.
49+
pub(crate) fn read_checksum(&mut self) -> Result<u32, IoError> {
50+
let i = self.read_up_to(4)?;
51+
assert_eq!(i, 4);
52+
let bytes: [u8; 4] = self.buf[.. 4].try_into().unwrap();
53+
Ok(u32::from_be_bytes(bytes))
54+
}
4555
}

src/validate.rs

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -124,31 +124,23 @@ impl<I: Read + Write + Seek> CrcStore<I> {
124124
/// last 4 bytes.
125125
fn process_segment(&mut self, hasher: &mut Hasher) -> Result<u32, IoError> {
126126
let s = self.cfg.seg_len as u64;
127-
let end_of_seg = s - (self.inner_pos % s);
128-
let end_of_inner = self.inner_len - self.inner_pos;
129-
let n = min(end_of_inner, end_of_seg) as usize;
130-
let b = self.cfg.buf_len as usize;
131-
if n <= b {
132-
self.process_segment_end(hasher, n)
133-
} else {
134-
assert!(n > b);
135-
let i = self.read_up_to(b)?;
136-
let body = &self.buf[.. i];
137-
hasher.update(body);
138-
self.process_segment(hasher)
127+
let buf_len = self.cfg.buf_len as usize;
128+
loop {
129+
let to_next_seg = s - (self.inner_pos % s);
130+
let to_end_of_inner = self.inner_len - self.inner_pos;
131+
let remain = min(to_next_seg, to_end_of_inner);
132+
if remain == 4 {
133+
return self.read_checksum();
134+
} else if remain < 4 {
135+
panic!("internal error");
136+
} else {
137+
let body_remain = (remain - 4) as usize;
138+
let to_read = min(body_remain, buf_len);
139+
let i = self.read_up_to(to_read)?;
140+
assert_eq!(i, to_read);
141+
let body = &self.buf[.. i];
142+
hasher.update(body);
143+
}
139144
}
140145
}
141-
142-
/// Reads up to `n` bytes from the `inner` I/O object using the
143-
/// pre-allocated `self.buf` buffer. Updates the `hasher` accordingly.
144-
/// Returns the checksum from the last 4 bytes read.
145-
fn process_segment_end(&mut self, hasher: &mut Hasher, n: usize) -> Result<u32, IoError> {
146-
assert!(n <= self.cfg.buf_len as usize);
147-
let i = self.read_up_to(n)?;
148-
let body = &self.buf[.. i - 4];
149-
hasher.update(body);
150-
let last4: [u8; 4] = self.buf[i - 4 .. i].try_into().unwrap();
151-
let read_checksum = u32::from_be_bytes(last4);
152-
Ok(read_checksum)
153-
}
154146
}

0 commit comments

Comments
 (0)