use super::{ChunkAddress, XorName};
use bytes::Bytes;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Hash, Eq, PartialEq, PartialOrd, Ord, Clone, custom_debug::Debug)]
pub struct Chunk {
address: ChunkAddress,
#[debug(skip)]
value: Bytes,
}
impl Chunk {
pub fn new(value: Bytes) -> Self {
Self {
address: ChunkAddress(XorName::from_content(value.as_ref())),
value,
}
}
pub fn value(&self) -> &Bytes {
&self.value
}
pub fn address(&self) -> &ChunkAddress {
&self.address
}
pub fn name(&self) -> &XorName {
self.address.name()
}
pub fn payload_size(&self) -> usize {
self.value.len()
}
pub fn serialised_size(&self) -> usize {
self.value.len()
}
}
impl Serialize for Chunk {
fn serialize<S: Serializer>(&self, serialiser: S) -> Result<S::Ok, S::Error> {
self.value.serialize(serialiser)
}
}
impl<'de> Deserialize<'de> for Chunk {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = Deserialize::deserialize(deserializer)?;
Ok(Self::new(value))
}
}
#[cfg(test)]
mod tests {
use crate::types::{utils, Chunk, Error, Result};
use bytes::Bytes;
use hex::encode;
use rand_07::{self, Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
use std::{env, iter, thread};
#[test]
fn deterministic_name() {
let bytes1 = Bytes::from(b"Hello".to_vec());
let bytes2 = Bytes::from(b"Goodbye".to_vec());
let chunk1 = Chunk::new(bytes1.clone());
let chunk2 = Chunk::new(bytes2.clone());
let chunk3 = Chunk::new(bytes1);
let chunk4 = Chunk::new(bytes2);
assert_eq!(chunk1.name(), chunk3.name());
assert_eq!(chunk2.name(), chunk4.name());
assert_ne!(chunk1.name(), chunk2.name());
assert_ne!(chunk3.name(), chunk4.name());
}
#[test]
fn deterministic_address() -> Result<()> {
let bytes1 = Bytes::from(b"Hello".to_vec());
let bytes2 = Bytes::from(b"Goodbye".to_vec());
let chunk1 = Chunk::new(bytes1.clone());
let chunk2 = Chunk::new(bytes2.clone());
let chunk3 = Chunk::new(bytes1);
let chunk4 = Chunk::new(bytes2);
assert_eq!(chunk1.address(), chunk3.address());
assert_eq!(chunk2.address(), chunk4.address());
assert_ne!(chunk1.address(), chunk2.address());
assert_ne!(chunk3.address(), chunk4.address());
assert_ne!(
bincode::serialize(chunk1.address()).map_err(|_| Error::Serialisation(
"Test address serialisation failed".to_string()
))?,
bincode::serialize(chunk2.address()).map_err(|_| Error::Serialisation(
"Test address serialisation failed".to_string()
))?
);
Ok(())
}
#[test]
fn deterministic_test() {
let value = Bytes::from(b"immutable chunk value".to_vec());
let chunk = Chunk::new(value);
let chunk_name = encode(chunk.name().0.as_ref());
let expected_name = "920f9a03bc90af3a7bfaf50c03abd5ff5b1579bd4006ba28eebcf240d4922519";
assert_eq!(&expected_name, &chunk_name);
}
#[test]
fn serialisation() -> Result<()> {
let mut rng = get_rng();
let len = rng.gen_range(1, 10_000);
let value = iter::repeat_with(|| rng.gen()).take(len).collect();
let chunk = Chunk::new(value);
let serialised = utils::serialise(&chunk)?;
let parsed = utils::deserialise(&serialised)?;
assert_eq!(chunk, parsed);
Ok(())
}
fn get_rng() -> XorShiftRng {
let env_var_name = "RANDOM_SEED";
let seed = env::var(env_var_name)
.map(|res| res.parse::<u64>().unwrap_or_else(|_| rand::random()))
.unwrap_or_else(|_| rand::random());
println!(
"To replay this '{}', set env var {}={}",
thread::current().name().unwrap_or(""),
env_var_name,
seed
);
XorShiftRng::seed_from_u64(seed)
}
}