use std::fmt;
use std::sync::Arc;
use rand;
use rand::Rng;
use rustc_serialize::hex::FromHex;
use rustc_serialize::hex::ToHex;
use zbackup::disk_format::*;
pub const KEY_SIZE: usize = 16;
pub const HMAC_SIZE: usize = 20;
pub const IV_SIZE: usize = 16;
pub const BUFFER_SIZE: usize = 0x2000;
#[ doc (hidden) ]
pub const WORK_JOBS_TOTAL: usize = 0;
#[ doc (hidden) ]
pub const WORK_JOBS_BATCH: usize = 0;
#[ derive (Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd) ]
pub struct BundleId {
bytes: [u8; 24],
}
impl BundleId {
#[ inline ]
pub fn random () -> BundleId {
BundleId {
bytes: random_array_24 (),
}
}
#[ inline ]
pub fn from_slice (
bytes: & [u8],
) -> Result <BundleId, String> {
Ok (BundleId {
bytes: to_array_24 (
bytes.iter ().map (|& byte| byte),
) ?,
})
}
#[ inline ]
pub fn parse <
BundleIdString: AsRef <str>,
> (
bundle_id_string: BundleIdString,
) -> Result <BundleId, String> {
Ok (BundleId {
bytes: parse_array_24 (
"bundle id",
bundle_id_string.as_ref (),
) ?,
})
}
#[ inline ]
pub fn bytes (& self) -> & [u8] {
& self.bytes
}
#[ inline ]
pub fn into_vec (self) -> Vec <u8> {
self.bytes.to_vec ()
}
#[ inline ]
pub fn to_string (& self) -> String {
self.bytes.to_hex ()
}
}
impl fmt::Display for BundleId {
fn fmt (
& self,
formatter: & mut fmt::Formatter,
) -> Result <(), fmt::Error> {
formatter.write_str (
& self.bytes.to_hex (),
)
}
}
impl fmt::Debug for BundleId {
fn fmt (
& self,
formatter: & mut fmt::Formatter,
) -> Result <(), fmt::Error> {
write! (
formatter,
"BundleId ({})",
self,
)
}
}
#[ derive (Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd) ]
pub struct ChunkId {
bytes: [u8; 24],
}
impl ChunkId {
#[ inline ]
pub fn random () -> ChunkId {
ChunkId {
bytes: random_array_24 (),
}
}
#[ inline ]
pub fn from_slice (
bytes: & [u8],
) -> Result <ChunkId, String> {
Ok (ChunkId {
bytes: to_array_24 (
bytes.iter ().map (|& byte| byte),
) ?,
})
}
#[ inline ]
pub fn parse <
ChunkIdString: AsRef <str>,
> (
chunk_id_string: ChunkIdString,
) -> Result <ChunkId, String> {
Ok (ChunkId {
bytes: parse_array_24 (
"chunk id",
chunk_id_string.as_ref (),
) ?,
})
}
#[ inline ]
pub fn bytes (& self) -> & [u8] {
& self.bytes
}
#[ inline ]
pub fn into_vec (self) -> Vec <u8> {
self.bytes.to_vec ()
}
#[ inline ]
pub fn to_string (& self) -> String {
self.bytes.to_hex ()
}
}
impl From <[u8; 24]> for ChunkId {
fn from (
bytes: [u8; 24],
) -> ChunkId {
ChunkId {
bytes: bytes,
}
}
}
impl fmt::Display for ChunkId {
fn fmt (
& self,
formatter: & mut fmt::Formatter,
) -> Result <(), fmt::Error> {
formatter.write_str (
& self.bytes.to_hex (),
)
}
}
#[ derive (Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd) ]
pub struct IndexId {
bytes: [u8; 24],
}
impl IndexId {
#[ inline ]
pub fn random () -> IndexId {
IndexId {
bytes: random_array_24 (),
}
}
#[ inline ]
pub fn parse <
IndexIdString: AsRef <str>,
> (
index_id_string: IndexIdString,
) -> Result <IndexId, String> {
Ok (IndexId {
bytes: parse_array_24 (
"index id",
index_id_string.as_ref (),
) ?,
} )
}
#[ inline ]
pub fn into_vec (self) -> Vec <u8> {
self.bytes.to_vec ()
}
#[ inline ]
pub fn to_string (& self) -> String {
self.bytes.to_hex ()
}
}
impl From <[u8; 24]> for IndexId {
fn from (
bytes: [u8; 24],
) -> IndexId {
IndexId {
bytes: bytes,
}
}
}
impl fmt::Display for IndexId {
fn fmt (
& self,
formatter: & mut fmt::Formatter,
) -> Result <(), fmt::Error> {
formatter.write_str (
& self.bytes.to_hex (),
)
}
}
pub fn to_array_24 <
ItemsIntoIter: IntoIterator <Item = u8>,
> (
items_into_iter: ItemsIntoIter,
) -> Result <[u8; 24], String> {
let mut items_iter =
items_into_iter.into_iter ();
let array = [
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
items_iter.next ().ok_or_else (|| "Not enough data".to_string ()) ?,
];
if items_iter.next ().is_some () {
return Err ("Too much data".to_string ());
}
Ok (array)
}
pub fn parse_array_24 (
name: & str,
string: & str,
) -> Result <[u8; 24], String> {
if string.len () != 48 {
Err (
format! (
"Invalid {}: {}",
name,
string))
} else {
Ok (to_array_24 (
string.from_hex ().map_err (|_|
format! (
"Invalid {}: {}",
name,
string)
) ?.into_iter (),
) ?)
}
}
pub fn random_array_24 () -> [u8; 24] {
to_array_24 (
rand::thread_rng ()
.gen_iter::<u8> ()
.take (24)
).unwrap ()
}
pub type ChunkData = Arc <Vec <u8>>;
pub type EncryptionKey = [u8; KEY_SIZE];
pub struct RawIndexEntry {
pub index_bundle_header: DiskIndexBundleHeader,
pub bundle_info: DiskBundleInfo,
}
pub const MAX_UNCOMPRESSED_MEMORY_CACHE_ENTRIES: usize = 0x10;
pub const MAX_COMPRESSED_MEMORY_CACHE_ENTRIES: usize = 0x100;
pub const MAX_COMPRESSED_FILESYSTEM_CACHE_ENTRIES: usize = 0x4000;
pub const FILESYSTEM_CACHE_PATH: & 'static str = "/tmp/rzbackup-cache";