2019-05-23 10:29:33 +00:00
|
|
|
use failure::*;
|
|
|
|
use futures::*;
|
|
|
|
|
|
|
|
pub struct ChunkInfo {
|
|
|
|
pub digest: [u8; 32],
|
|
|
|
pub data: bytes::BytesMut,
|
|
|
|
pub offset: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum MergedChunkInfo {
|
2019-05-24 05:42:58 +00:00
|
|
|
Known(Vec<(u64,[u8;32])>),
|
2019-05-23 10:29:33 +00:00
|
|
|
New(ChunkInfo),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait MergeKnownChunks: Sized {
|
2019-05-26 08:52:56 +00:00
|
|
|
fn merge_known_chunks(self) -> MergeKnownChunksQueue<Self>;
|
2019-05-23 10:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct MergeKnownChunksQueue<S> {
|
|
|
|
input: S,
|
2019-05-24 05:36:09 +00:00
|
|
|
buffer: Option<MergedChunkInfo>,
|
2019-05-23 10:29:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl <S> MergeKnownChunks for S
|
2019-05-26 08:52:56 +00:00
|
|
|
where S: Stream<Item=MergedChunkInfo, Error=Error>,
|
2019-05-23 10:29:33 +00:00
|
|
|
{
|
2019-05-26 08:52:56 +00:00
|
|
|
fn merge_known_chunks(self) -> MergeKnownChunksQueue<Self> {
|
|
|
|
MergeKnownChunksQueue { input: self, buffer: None }
|
2019-05-23 10:29:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl <S> Stream for MergeKnownChunksQueue<S>
|
2019-05-26 08:52:56 +00:00
|
|
|
where S: Stream<Item=MergedChunkInfo, Error=Error>,
|
2019-05-23 10:29:33 +00:00
|
|
|
{
|
|
|
|
type Item = MergedChunkInfo;
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<Option<MergedChunkInfo>, Error> {
|
|
|
|
loop {
|
|
|
|
match self.input.poll() {
|
|
|
|
Err(err) => {
|
|
|
|
return Err(err);
|
|
|
|
}
|
|
|
|
Ok(Async::NotReady) => {
|
|
|
|
return Ok(Async::NotReady);
|
|
|
|
}
|
|
|
|
Ok(Async::Ready(None)) => {
|
2019-05-24 05:36:09 +00:00
|
|
|
if let Some(last) = self.buffer.take() {
|
|
|
|
return Ok(Async::Ready(Some(last)));
|
2019-05-23 10:29:33 +00:00
|
|
|
} else {
|
2019-05-24 05:36:09 +00:00
|
|
|
return Ok(Async::Ready(None));
|
2019-05-23 10:29:33 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-26 08:52:56 +00:00
|
|
|
Ok(Async::Ready(Some(mergerd_chunk_info))) => {
|
2019-05-23 10:29:33 +00:00
|
|
|
|
2019-05-26 08:52:56 +00:00
|
|
|
match mergerd_chunk_info {
|
|
|
|
MergedChunkInfo::Known(list) => {
|
2019-05-23 10:29:33 +00:00
|
|
|
|
2019-05-26 08:52:56 +00:00
|
|
|
let last = self.buffer.take();
|
2019-05-23 10:29:33 +00:00
|
|
|
|
2019-05-26 08:52:56 +00:00
|
|
|
match last {
|
|
|
|
None => {
|
|
|
|
self.buffer = Some(MergedChunkInfo::Known(list));
|
|
|
|
// continue
|
2019-05-24 05:36:09 +00:00
|
|
|
}
|
2019-05-26 08:52:56 +00:00
|
|
|
Some(MergedChunkInfo::Known(mut last_list)) => {
|
|
|
|
last_list.extend_from_slice(&list);
|
|
|
|
let len = last_list.len();
|
|
|
|
self.buffer = Some(MergedChunkInfo::Known(last_list));
|
2019-05-24 05:36:09 +00:00
|
|
|
|
2019-05-26 08:52:56 +00:00
|
|
|
if len >= 64 {
|
|
|
|
return Ok(Async::Ready(self.buffer.take()));
|
|
|
|
}
|
|
|
|
// continue
|
|
|
|
}
|
|
|
|
Some(MergedChunkInfo::New(_)) => {
|
|
|
|
self.buffer = Some(MergedChunkInfo::Known(list));
|
|
|
|
return Ok(Async::Ready(last));
|
|
|
|
}
|
2019-05-23 10:29:33 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-26 08:52:56 +00:00
|
|
|
MergedChunkInfo::New(chunk_info) => {
|
|
|
|
let new = MergedChunkInfo::New(chunk_info);
|
|
|
|
if let Some(last) = self.buffer.take() {
|
|
|
|
self.buffer = Some(new);
|
|
|
|
return Ok(Async::Ready(Some(last)));
|
|
|
|
} else {
|
|
|
|
return Ok(Async::Ready(Some(new)));
|
|
|
|
}
|
2019-05-24 05:36:09 +00:00
|
|
|
}
|
2019-05-23 10:29:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|