use std::fmt::{Debug, Error, Formatter};
#[derive(RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ChunkDetails {
pub chunk_num: u32,
pub hash: Vec<u8>,
pub pre_hash: Vec<u8>,
pub source_size: u64,
}
fn debug_bytes<V: AsRef<[u8]>>(input: V) -> String {
use std::fmt::Write;
let input_ref = input.as_ref();
if input_ref.is_empty() {
return "<empty>".to_owned();
}
if input_ref.len() <= 6 {
let mut ret = String::new();
for byte in input_ref.iter() {
unwrap_result!(write!(ret, "{:02x}", byte));
}
return ret;
}
format!("{:02x}{:02x}{:02x}..{:02x}{:02x}{:02x}",
input_ref[0],
input_ref[1],
input_ref[2],
input_ref[input_ref.len() - 3],
input_ref[input_ref.len() - 2],
input_ref[input_ref.len() - 1])
}
impl ChunkDetails {
pub fn new() -> ChunkDetails {
ChunkDetails {
chunk_num: 0,
hash: vec![],
pre_hash: vec![],
source_size: 0,
}
}
}
impl Debug for ChunkDetails {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
write!(formatter,
"ChunkDetails {{ chunk_num: {}, hash: {}, pre_hash: {}, source_size: {} }}",
self.chunk_num,
debug_bytes(&self.hash),
debug_bytes(&self.pre_hash),
self.source_size)
}
}
#[derive(RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum DataMap {
Chunks(Vec<ChunkDetails>),
Content(Vec<u8>),
None,
}
#[cfg_attr(feature="clippy", allow(len_without_is_empty))]
impl DataMap {
pub fn len(&self) -> u64 {
match *self {
DataMap::Chunks(ref chunks) => DataMap::chunks_size(chunks),
DataMap::Content(ref content) => content.len() as u64,
DataMap::None => 0,
}
}
pub fn get_chunks(&self) -> Vec<ChunkDetails> {
match *self {
DataMap::Chunks(ref chunks) => chunks.to_vec(),
_ => panic!("no chunks"),
}
}
pub fn get_sorted_chunks(&self) -> Vec<ChunkDetails> {
match *self {
DataMap::Chunks(ref chunks) => {
let mut result = chunks.to_vec();
DataMap::chunks_sort(&mut result);
result
}
_ => panic!("no chunks"),
}
}
pub fn has_chunks(&self) -> bool {
match *self {
DataMap::Chunks(ref chunks) => DataMap::chunks_size(chunks) > 0,
_ => false,
}
}
fn chunks_size(chunks: &[ChunkDetails]) -> u64 {
chunks.iter().fold(0, |acc, chunk| acc + chunk.source_size)
}
fn chunks_sort(chunks: &mut [ChunkDetails]) {
chunks.sort_by(|a, b| a.chunk_num.cmp(&b.chunk_num));
}
}
impl Debug for DataMap {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
match *self {
DataMap::Chunks(ref chunks) => {
try!(write!(formatter, "DataMap::Chunks:\n"));
let len = chunks.len();
for (index, chunk) in chunks.iter().enumerate() {
if index + 1 == len {
try!(write!(formatter, " {:?}", chunk))
} else {
try!(write!(formatter, " {:?}\n", chunk))
}
}
Ok(())
}
DataMap::Content(ref content) => {
write!(formatter, "DataMap::Content({})", debug_bytes(content))
}
DataMap::None => write!(formatter, "DataMap::None"),
}
}
}