mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +03:00
implement read_multi with an internal iterating reader (#1981)
* rework read_multi to use an "iterating reader" internally we are going to use this for reading headers in batches * rustfmt
This commit is contained in:
parent
fb3f967a86
commit
2e421191e2
1 changed files with 45 additions and 3 deletions
|
@ -25,6 +25,7 @@ use core::hash::{Hash, Hashed};
|
|||
use keychain::{BlindingFactor, Identifier, IDENTIFIER_SIZE};
|
||||
use std::fmt::Debug;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::marker;
|
||||
use std::{cmp, error, fmt};
|
||||
use util::secp::constants::{
|
||||
AGG_SIGNATURE_SIZE, MAX_PROOF_SIZE, PEDERSEN_COMMITMENT_SIZE, SECRET_KEY_SIZE,
|
||||
|
@ -46,6 +47,8 @@ pub enum Error {
|
|||
},
|
||||
/// Data wasn't in a consumable format
|
||||
CorruptedData,
|
||||
/// Incorrect number of elements (when deserializing a vec via read_multi say).
|
||||
CountError,
|
||||
/// When asked to read too much data
|
||||
TooLargeReadErr,
|
||||
/// Consensus rule failure (currently sort order)
|
||||
|
@ -75,6 +78,7 @@ impl fmt::Display for Error {
|
|||
received: ref r,
|
||||
} => write!(f, "expected {:?}, got {:?}", e, r),
|
||||
Error::CorruptedData => f.write_str("corrupted data"),
|
||||
Error::CountError => f.write_str("count error"),
|
||||
Error::TooLargeReadErr => f.write_str("too large read"),
|
||||
Error::ConsensusError(ref e) => write!(f, "consensus error {:?}", e),
|
||||
Error::HexError(ref e) => write!(f, "hex error {:?}", e),
|
||||
|
@ -95,6 +99,7 @@ impl error::Error for Error {
|
|||
Error::IOErr(ref e, _) => e,
|
||||
Error::UnexpectedData { .. } => "unexpected data",
|
||||
Error::CorruptedData => "corrupted data",
|
||||
Error::CountError => "count error",
|
||||
Error::TooLargeReadErr => "too large read",
|
||||
Error::ConsensusError(_) => "consensus error (sort order)",
|
||||
Error::HexError(_) => "hex error",
|
||||
|
@ -201,10 +206,44 @@ pub trait Writeable {
|
|||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
struct IteratingReader<'a, T> {
|
||||
count: u64,
|
||||
curr: u64,
|
||||
reader: &'a mut Reader,
|
||||
_marker: marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> IteratingReader<'a, T> {
|
||||
fn new(reader: &'a mut Reader, count: u64) -> IteratingReader<'a, T> {
|
||||
let curr = 0;
|
||||
IteratingReader {
|
||||
count,
|
||||
curr,
|
||||
reader,
|
||||
_marker: marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator for IteratingReader<'a, T>
|
||||
where
|
||||
T: Readable,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
if self.curr >= self.count {
|
||||
return None;
|
||||
}
|
||||
self.curr += 1;
|
||||
T::read(self.reader).ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads multiple serialized items into a Vec.
|
||||
pub fn read_multi<T>(reader: &mut Reader, count: u64) -> Result<Vec<T>, Error>
|
||||
where
|
||||
T: Readable + Hashed + Writeable,
|
||||
T: Readable,
|
||||
{
|
||||
// Very rudimentary check to ensure we do not overflow anything
|
||||
// attempting to read huge amounts of data.
|
||||
|
@ -213,8 +252,11 @@ where
|
|||
return Err(Error::TooLargeReadErr);
|
||||
}
|
||||
|
||||
let result: Vec<T> = try!((0..count).map(|_| T::read(reader)).collect());
|
||||
Ok(result)
|
||||
let res: Vec<T> = IteratingReader::new(reader, count).collect();
|
||||
if res.len() as u64 != count {
|
||||
return Err(Error::CountError);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Trait that every type that can be deserialized from binary must implement.
|
||||
|
|
Loading…
Reference in a new issue