3 use bytes
::{Bytes, BytesMut}
;
5 /// Trait to get digest list from index files
7 /// To allow easy iteration over all used chunks.
8 pub trait IndexFile
: Send
{
9 fn index_count(&self) -> usize;
10 fn index_digest(&self, pos
: usize) -> Option
<&[u8; 32]>;
11 fn index_bytes(&self) -> u64;
14 /// Encode digest list from an `IndexFile` into a binary stream
16 /// The reader simply returns a birary stream of 32 byte digest values.
17 pub struct DigestListEncoder
{
18 index
: Box
<dyn IndexFile
>,
23 impl DigestListEncoder
{
25 pub fn new(index
: Box
<dyn IndexFile
>) -> Self {
26 let count
= index
.index_count();
27 Self { index, pos: 0, count }
31 impl std
::io
::Read
for DigestListEncoder
{
33 fn read(&mut self, buf
: &mut [u8]) -> Result
<usize, std
::io
::Error
> {
34 if buf
.len() < 32 { panic!("read buffer too small"); }
35 if self.pos
< self.count
{
38 let digest
= self.index
.index_digest(self.pos
).unwrap();
39 unsafe { std::ptr::copy_nonoverlapping(digest.as_ptr(), buf.as_mut_ptr().add(written), 32); }
42 if self.pos
>= self.count { break; }
43 if (written
+ 32) >= buf
.len() { break; }
52 /// Decodes a Stream<Item=Bytes> into Stream<Item=<[u8;32]>
54 /// The reader simply returns a birary stream of 32 byte digest values.
56 pub struct DigestListDecoder
<S
> {
61 impl <S
> DigestListDecoder
<S
> {
63 pub fn new(input
: S
) -> Self {
64 Self { input, buffer: BytesMut::new() }
68 impl <S
> Stream
for DigestListDecoder
<S
>
69 where S
: Stream
<Item
=Bytes
>,
70 S
::Error
: Into
<Error
>,
75 fn poll(&mut self) -> Result
<Async
<Option
<Self::Item
>>, Self::Error
> {
78 if self.buffer
.len() >= 32 {
80 let left
= self.buffer
.split_to(32);
82 let mut digest
: [u8; 32] = unsafe { std::mem::uninitialized() }
;
83 unsafe { std::ptr::copy_nonoverlapping(left.as_ptr(), digest.as_mut_ptr(), 32); }
85 return Ok(Async
::Ready(Some(digest
)));
88 match self.input
.poll() {
90 return Err(err
.into());
92 Ok(Async
::NotReady
) => {
93 return Ok(Async
::NotReady
);
95 Ok(Async
::Ready(None
)) => {
96 let rest
= self.buffer
.len();
97 if rest
== 0 { return Ok(Async::Ready(None)); }
98 return Err(format_err
!("got small digest ({} != 32).", rest
));
100 Ok(Async
::Ready(Some(data
))) => {
101 self.buffer
.extend_from_slice(&data
);