From 87a19add6094aefd0c2dc794da015a14db10b8a7 Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 11:34:44 +0100 Subject: [PATCH 1/8] Getter for EncoderWork.recovery_count --- src/rate/encoder_work.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rate/encoder_work.rs b/src/rate/encoder_work.rs index 8596b15..178a355 100644 --- a/src/rate/encoder_work.rs +++ b/src/rate/encoder_work.rs @@ -120,4 +120,8 @@ impl EncoderWork { self.shards .undo_last_chunk_encoding(self.shard_bytes, 0..self.recovery_count); } + + pub(crate) fn recovery_count(&self) -> usize { + self.recovery_count + } } From 60c96ba423feac6a16988b304edcda342be8fd59 Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 11:34:07 +0100 Subject: [PATCH 2/8] impl ExactSizeIterator for Recovery --- src/encoder_result.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/encoder_result.rs b/src/encoder_result.rs index 3c84562..dff2d88 100644 --- a/src/encoder_result.rs +++ b/src/encoder_result.rs @@ -79,8 +79,18 @@ impl<'a> Iterator for Recovery<'a> { None } } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.work.recovery_count() - self.next_index; + (remaining, Some(remaining)) + } } +// ====================================================================== +// Recovery - IMPL ExactSizeIterator + +impl ExactSizeIterator for Recovery<'_> {} + // ====================================================================== // Recovery - CRATE From 0914bb99de57bda5755e9e7d1032a5c441e68a32 Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 11:51:24 +0100 Subject: [PATCH 3/8] Add test: encoder_result_size_hint (ExactSizeIterator test) --- src/encoder_result.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/encoder_result.rs b/src/encoder_result.rs index dff2d88..8ec349d 100644 --- a/src/encoder_result.rs +++ b/src/encoder_result.rs @@ -141,4 +141,30 @@ mod tests { assert!(iter.next().is_none()); test_util::assert_hash(all, test_util::LOW_2_3); } + + #[test] + fn encoder_result_size_hint() { + let original = test_util::generate_original(2, 1024, 123); + let mut encoder = ReedSolomonEncoder::new(2, 3, 1024).unwrap(); + + for original in &original { + encoder.add_original_shard(original).unwrap(); + } + + let result: EncoderResult = encoder.encode().unwrap(); + + let mut iter: Recovery = result.recovery_iter(); + + assert_eq!(iter.len(), 3); + + assert!(iter.next().is_some()); + assert!(iter.next().is_some()); + assert_eq!(iter.len(), 1); + + assert!(iter.next().is_some()); + assert_eq!(iter.len(), 0); + + assert!(iter.next().is_none()); + assert_eq!(iter.len(), 0); + } } From 4bfa85f8b1bf50ef6f7dc931914cc8f83486b9c2 Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 13:25:20 +0100 Subject: [PATCH 4/8] DecoderWork: missing_original_count --- src/rate/decoder_work.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rate/decoder_work.rs b/src/rate/decoder_work.rs index bd8bcf2..ec44622 100644 --- a/src/rate/decoder_work.rs +++ b/src/rate/decoder_work.rs @@ -202,4 +202,8 @@ impl DecoderWork { self.original_base_pos..self.original_base_pos + self.original_count, ); } + + pub(crate) fn missing_original_count(&self) -> usize { + self.original_count - self.original_received_count + } } From 342217377d72adf3f90bdf90eba12a55d8af9ee3 Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 13:26:01 +0100 Subject: [PATCH 5/8] DecoderResult: size_hint --- src/decoder_result.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/decoder_result.rs b/src/decoder_result.rs index 452710f..5dfacc8 100644 --- a/src/decoder_result.rs +++ b/src/decoder_result.rs @@ -80,6 +80,11 @@ impl<'a> Iterator for RestoredOriginal<'a> { None } } + + fn size_hint(&self) -> (usize, Option) { + let max_remaining = self.work.missing_original_count(); + (0, Some(max_remaining)) + } } // ====================================================================== From 33e1456747a62291df92bd0f441273a7709f3024 Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 13:39:51 +0100 Subject: [PATCH 6/8] DecoderResult: Keep track of `remaining` --- src/decoder_result.rs | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/decoder_result.rs b/src/decoder_result.rs index 5dfacc8..21a853d 100644 --- a/src/decoder_result.rs +++ b/src/decoder_result.rs @@ -54,7 +54,7 @@ impl Drop for DecoderResult<'_> { /// /// This struct is created by [`DecoderResult::restored_original_iter`]. pub struct RestoredOriginal<'a> { - ended: bool, + remaining: usize, next_index: usize, work: &'a DecoderWork, } @@ -65,25 +65,27 @@ pub struct RestoredOriginal<'a> { impl<'a> Iterator for RestoredOriginal<'a> { type Item = (usize, &'a [u8]); fn next(&mut self) -> Option<(usize, &'a [u8])> { - if self.ended { - None - } else { - let mut index = self.next_index; - while index < self.work.original_count() { - if let Some(original) = self.work.restored_original(index) { - self.next_index = index + 1; - return Some((index, original)); - } - index += 1; + if self.remaining == 0 { + return None; + } + + let mut index = self.next_index; + while index < self.work.original_count() { + if let Some(original) = self.work.restored_original(index) { + self.next_index = index + 1; + self.remaining -= 1; + return Some((index, original)); } - self.ended = true; - None + index += 1; } + + // If we reach this point, there's an inconsistency in the internal data structures. + debug_assert!(false); + None } fn size_hint(&self) -> (usize, Option) { - let max_remaining = self.work.missing_original_count(); - (0, Some(max_remaining)) + (self.remaining, Some(self.remaining)) } } @@ -93,7 +95,7 @@ impl<'a> Iterator for RestoredOriginal<'a> { impl<'a> RestoredOriginal<'a> { pub(crate) fn new(work: &'a DecoderWork) -> Self { Self { - ended: false, + remaining: work.missing_original_count(), next_index: 0, work, } From c00bcf1d372267a3fbd70ae2151c96e774bf8e9d Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 13:41:25 +0100 Subject: [PATCH 7/8] impl ExactSizeIterator for RestoredOriginal --- src/decoder_result.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/decoder_result.rs b/src/decoder_result.rs index 21a853d..258bb6e 100644 --- a/src/decoder_result.rs +++ b/src/decoder_result.rs @@ -89,6 +89,11 @@ impl<'a> Iterator for RestoredOriginal<'a> { } } +// ====================================================================== +// RestoredOriginal - IMPL ExactSizeIterator + +impl ExactSizeIterator for RestoredOriginal<'_> {} + // ====================================================================== // RestoredOriginal - CRATE From fbb7aa63df05058fb14de02095279675a94a3de6 Mon Sep 17 00:00:00 2001 From: AndersTrier Date: Mon, 25 Nov 2024 13:44:48 +0100 Subject: [PATCH 8/8] test: decoder_result_size_hint --- src/decoder_result.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/decoder_result.rs b/src/decoder_result.rs index 258bb6e..2bfc059 100644 --- a/src/decoder_result.rs +++ b/src/decoder_result.rs @@ -162,4 +162,39 @@ mod tests { simple_roundtrip(shard_size); } } + + #[test] + fn decoder_result_size_hint() { + let shard_size = 64; + let original = test_util::generate_original(3, shard_size, 0); + + let mut encoder = ReedSolomonEncoder::new(3, 2, shard_size).unwrap(); + let mut decoder = ReedSolomonDecoder::new(3, 2, shard_size).unwrap(); + + for original in &original { + encoder.add_original_shard(original).unwrap(); + } + + let result = encoder.encode().unwrap(); + let recovery: Vec<_> = result.recovery_iter().collect(); + + decoder.add_original_shard(1, &original[1]).unwrap(); + decoder.add_recovery_shard(0, recovery[0]).unwrap(); + decoder.add_recovery_shard(1, recovery[1]).unwrap(); + + let result: DecoderResult = decoder.decode().unwrap(); + + let mut iter: RestoredOriginal = result.restored_original_iter(); + + assert_eq!(iter.len(), 2); + + assert!(iter.next().is_some()); + assert_eq!(iter.len(), 1); + + assert!(iter.next().is_some()); + assert_eq!(iter.len(), 0); + + assert!(iter.next().is_none()); + assert_eq!(iter.len(), 0); + } }