zvault/src/util/chunk.rs

126 lines
2.9 KiB
Rust

use std::io::{self, Write, Read, Cursor};
use std::ops::{Deref, DerefMut};
use serde::{self, Serialize, Deserialize};
use serde::bytes::{Bytes, ByteBuf};
use serde::de::Error;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use super::Hash;
pub type Chunk = (Hash, u32);
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct ChunkList(Vec<Chunk>);
impl ChunkList {
#[inline]
pub fn new() -> Self {
ChunkList(Vec::new())
}
#[inline]
pub fn with_capacity(num: usize) -> Self {
ChunkList(Vec::with_capacity(num))
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn push(&mut self, chunk: Chunk) {
self.0.push(chunk)
}
#[inline]
pub fn write_to(&self, dst: &mut Write) -> Result<(), io::Error> {
for chunk in &self.0 {
try!(chunk.0.write_to(dst));
try!(dst.write_u32::<LittleEndian>(chunk.1));
}
Ok(())
}
#[inline]
pub fn read_n_from(n: usize, src: &mut Read) -> Result<Self, io::Error> {
let mut chunks = Vec::with_capacity(n);
for _ in 0..n {
let hash = try!(Hash::read_from(src));
let len = try!(src.read_u32::<LittleEndian>());
chunks.push((hash, len));
}
Ok(ChunkList(chunks))
}
#[inline]
pub fn read_from(src: &[u8]) -> Self {
if src.len() % 20 != 0 {
warn!("Reading truncated chunk list");
}
ChunkList::read_n_from(src.len()/20, &mut Cursor::new(src)).unwrap()
}
#[inline]
pub fn encoded_size(&self) -> usize {
self.0.len() * 20
}
}
impl Default for ChunkList {
#[inline]
fn default() -> Self {
ChunkList(Vec::new())
}
}
impl From<Vec<Chunk>> for ChunkList {
fn from(val: Vec<Chunk>) -> Self {
ChunkList(val)
}
}
impl Into<Vec<Chunk>> for ChunkList {
fn into(self) -> Vec<Chunk> {
self.0
}
}
impl Deref for ChunkList {
type Target = [Chunk];
fn deref(&self) -> &[Chunk] {
&self.0
}
}
impl DerefMut for ChunkList {
fn deref_mut(&mut self) -> &mut [Chunk] {
&mut self.0
}
}
impl Serialize for ChunkList {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
let mut buf = Vec::with_capacity(self.encoded_size());
self.write_to(&mut buf).unwrap();
Bytes::from(&buf as &[u8]).serialize(serializer)
}
}
impl Deserialize for ChunkList {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer {
let data: Vec<u8> = try!(ByteBuf::deserialize(deserializer)).into();
if data.len() % 20 != 0 {
return Err(D::Error::custom("Invalid chunk list length"));
}
Ok(ChunkList::read_n_from(data.len()/20, &mut Cursor::new(data)).unwrap())
}
}