mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +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 keychain::{BlindingFactor, Identifier, IDENTIFIER_SIZE};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
|
use std::marker;
|
||||||
use std::{cmp, error, fmt};
|
use std::{cmp, error, fmt};
|
||||||
use util::secp::constants::{
|
use util::secp::constants::{
|
||||||
AGG_SIGNATURE_SIZE, MAX_PROOF_SIZE, PEDERSEN_COMMITMENT_SIZE, SECRET_KEY_SIZE,
|
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
|
/// Data wasn't in a consumable format
|
||||||
CorruptedData,
|
CorruptedData,
|
||||||
|
/// Incorrect number of elements (when deserializing a vec via read_multi say).
|
||||||
|
CountError,
|
||||||
/// When asked to read too much data
|
/// When asked to read too much data
|
||||||
TooLargeReadErr,
|
TooLargeReadErr,
|
||||||
/// Consensus rule failure (currently sort order)
|
/// Consensus rule failure (currently sort order)
|
||||||
|
@ -75,6 +78,7 @@ impl fmt::Display for Error {
|
||||||
received: ref r,
|
received: ref r,
|
||||||
} => write!(f, "expected {:?}, got {:?}", e, r),
|
} => write!(f, "expected {:?}, got {:?}", e, r),
|
||||||
Error::CorruptedData => f.write_str("corrupted data"),
|
Error::CorruptedData => f.write_str("corrupted data"),
|
||||||
|
Error::CountError => f.write_str("count error"),
|
||||||
Error::TooLargeReadErr => f.write_str("too large read"),
|
Error::TooLargeReadErr => f.write_str("too large read"),
|
||||||
Error::ConsensusError(ref e) => write!(f, "consensus error {:?}", e),
|
Error::ConsensusError(ref e) => write!(f, "consensus error {:?}", e),
|
||||||
Error::HexError(ref e) => write!(f, "hex 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::IOErr(ref e, _) => e,
|
||||||
Error::UnexpectedData { .. } => "unexpected data",
|
Error::UnexpectedData { .. } => "unexpected data",
|
||||||
Error::CorruptedData => "corrupted data",
|
Error::CorruptedData => "corrupted data",
|
||||||
|
Error::CountError => "count error",
|
||||||
Error::TooLargeReadErr => "too large read",
|
Error::TooLargeReadErr => "too large read",
|
||||||
Error::ConsensusError(_) => "consensus error (sort order)",
|
Error::ConsensusError(_) => "consensus error (sort order)",
|
||||||
Error::HexError(_) => "hex error",
|
Error::HexError(_) => "hex error",
|
||||||
|
@ -201,10 +206,44 @@ pub trait Writeable {
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error>;
|
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.
|
/// Reads multiple serialized items into a Vec.
|
||||||
pub fn read_multi<T>(reader: &mut Reader, count: u64) -> Result<Vec<T>, Error>
|
pub fn read_multi<T>(reader: &mut Reader, count: u64) -> Result<Vec<T>, Error>
|
||||||
where
|
where
|
||||||
T: Readable + Hashed + Writeable,
|
T: Readable,
|
||||||
{
|
{
|
||||||
// Very rudimentary check to ensure we do not overflow anything
|
// Very rudimentary check to ensure we do not overflow anything
|
||||||
// attempting to read huge amounts of data.
|
// attempting to read huge amounts of data.
|
||||||
|
@ -213,8 +252,11 @@ where
|
||||||
return Err(Error::TooLargeReadErr);
|
return Err(Error::TooLargeReadErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: Vec<T> = try!((0..count).map(|_| T::read(reader)).collect());
|
let res: Vec<T> = IteratingReader::new(reader, count).collect();
|
||||||
Ok(result)
|
if res.len() as u64 != count {
|
||||||
|
return Err(Error::CountError);
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait that every type that can be deserialized from binary must implement.
|
/// Trait that every type that can be deserialized from binary must implement.
|
||||||
|
|
Loading…
Reference in a new issue