extern crate serde; extern crate serde_json; use std::cmp::Ordering; use std::convert::TryInto; use std::fmt; use std::fmt::{Error, Formatter}; use std::hash::{Hash, Hasher}; use std::ops::Deref; use num_bigint::BigUint; // For deserialization use serde::de::{Error as DeError, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[derive(Clone, Default)] pub struct Bytes { data: Vec } impl Bytes { pub fn new(data: Vec) -> Self { Bytes { data } } pub fn from_bytes(data: &[u8]) -> Self { Bytes { data: Vec::from(data) } } pub fn length(&self) -> usize { self.data.len() } pub fn is_empty(&self) -> bool { self.data.is_empty() } pub fn is_zero(&self) -> bool { if self.data.is_empty() { return true; } for x in self.data.iter() { if *x != 0 { return false; } } true } /// Returns a byte slice of the hash contents. pub fn as_slice(&self) -> &[u8] { self.data.as_slice() } /// Returns a mutable byte slice (to fill by hasher) pub fn as_mut_slice(&mut self) -> &mut [u8] { self.data.as_mut_slice() } #[allow(clippy::inherent_to_string)] pub fn to_string(&self) -> String { crate::commons::to_hex(&self.data) } pub fn get_tail_u64(&self) -> u64 { let index = self.data.len() - 8; let bytes: [u8; 8] = self.data[index..].try_into().unwrap(); u64::from_be_bytes(bytes) } pub fn zero32() -> Self { Bytes { data: [0u8; 32].to_vec() } } pub fn zero64() -> Self { Bytes { data: [0u8; 64].to_vec() } } } impl PartialEq for Bytes { fn eq(&self, other: &Self) -> bool { crate::blockchain::hash_utils::same_hash(self, other) } } impl Eq for Bytes {} impl PartialOrd for Bytes { fn partial_cmp(&self, other: &Self) -> Option { let self_hash_int = BigUint::from_bytes_le(self); let other_hash_int = BigUint::from_bytes_le(other); Some(self_hash_int.cmp(&other_hash_int)) } } impl Ord for Bytes { fn cmp(&self, other: &Self) -> Ordering { let self_hash_int = BigUint::from_bytes_le(self); let other_hash_int = BigUint::from_bytes_le(other); self_hash_int.cmp(&other_hash_int) } } impl Hash for Bytes { fn hash(&self, state: &mut H) { state.write(&self.data); } } impl Deref for Bytes { type Target = Vec; fn deref(&self) -> &Self::Target { &self.data } } impl fmt::Debug for Bytes { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str(&crate::commons::to_hex(&self.data)) } } impl Serialize for Bytes { fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> where S: Serializer { serializer.serialize_str(&crate::commons::to_hex(&self.data)) } } struct BytesVisitor; impl<'de> Visitor<'de> for BytesVisitor { type Value = Bytes; fn expecting(&self, formatter: &mut Formatter) -> Result<(), Error> { formatter.write_str("bytes in HEX format") } fn visit_str(self, value: &str) -> Result where E: DeError { if !value.is_empty() && value.len() % 2 == 0 { Ok(Bytes::new(crate::from_hex(value).unwrap())) } else if value.is_empty() { Ok(Bytes::default()) } else { Err(E::custom("Expected bytes in HEX format!")) } } fn visit_bytes(self, value: &[u8]) -> Result where E: DeError { if !value.is_empty() { Ok(Bytes::from_bytes(value)) } else { Ok(Bytes::default()) } } } impl<'dd> Deserialize<'dd> for Bytes { fn deserialize(deserializer: D) -> Result>::Error> where D: Deserializer<'dd> { deserializer.deserialize_str(BytesVisitor) } } #[cfg(test)] mod tests { use crate::blockchain::hash_utils::same_hash; use crate::bytes::Bytes; #[test] pub fn test_tail_bytes() { let bytes = Bytes::new(vec![0, 255, 255, 255, 0, 255, 255, 255]); assert_eq!(bytes.get_tail_u64(), 72057589759737855u64); } #[test] pub fn test_deref() { let bytes = Bytes::zero32(); assert!(same_hash(&bytes, &vec!(0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))); } }