use super::DataIdentifier;
use maidsafe_utilities::serialisation::serialised_size;
use rust_sodium::crypto::hash::sha256;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::fmt::{self, Debug, Formatter};
use xor_name::XorName;
pub const MAX_IMMUTABLE_DATA_SIZE_IN_BYTES: u64 = 1024 * 1024 + 10 * 1024;
#[derive(Hash, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct ImmutableData {
name: XorName,
value: Vec<u8>,
}
impl ImmutableData {
pub fn new(value: Vec<u8>) -> ImmutableData {
ImmutableData {
name: XorName(sha256::hash(&value).0),
value: value,
}
}
pub fn value(&self) -> &Vec<u8> {
&self.value
}
pub fn name(&self) -> &XorName {
&self.name
}
pub fn payload_size(&self) -> usize {
self.value.len()
}
pub fn identifier(&self) -> DataIdentifier {
DataIdentifier::Immutable(self.name)
}
pub fn validate_size(&self) -> bool {
serialised_size(self) <= MAX_IMMUTABLE_DATA_SIZE_IN_BYTES
}
}
impl Encodable for ImmutableData {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
self.value.encode(encoder)
}
}
impl Decodable for ImmutableData {
fn decode<D: Decoder>(decoder: &mut D) -> Result<ImmutableData, D::Error> {
let value: Vec<u8> = Decodable::decode(decoder)?;
Ok(ImmutableData {
name: XorName(sha256::hash(&value).0),
value: value,
})
}
}
impl Debug for ImmutableData {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "ImmutableData {:?}", self.name())
}
}
#[cfg(test)]
mod tests {
use super::*;
use rustc_serialize::hex::ToHex;
#[test]
fn deterministic_test() {
let value = "immutable data value".to_owned().into_bytes();
let immutable_data = ImmutableData::new(value);
let immutable_data_name = immutable_data.name()
.0
.as_ref()
.to_hex();
let expected_name = "ec0775555a7a6afba5f6e0a1deaa06f8928da80cf6ca94742ecc2a00c31033d3";
assert_eq!(&expected_name, &immutable_data_name);
}
}