use std::{
cmp::Ordering,
hash::{Hash, Hasher},
};
use ring::digest::{digest, SHA256};
use serde::{self, Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize, Eq)]
#[repr(transparent)]
pub struct Data(Vec<u8>);
impl Default for Data {
fn default() -> Self {
Self::default()
}
}
impl Data {
pub fn default() -> Self {
Data(Vec::new())
}
pub fn from_slice(d: &[u8]) -> Self {
Data(Vec::from(d))
}
}
impl AsRef<[u8]> for Data {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Ord for Data {
fn cmp(&self, other: &Data) -> Ordering {
let h1: Vec<u8> = digest(&SHA256, &self.0).as_ref().into();
let h2: Vec<u8> = digest(&SHA256, &other.0).as_ref().into();
h1.cmp(&(h2))
}
}
impl PartialOrd for Data {
fn partial_cmp(&self, other: &Data) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for Data {
fn eq(&self, other: &Data) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Hash for Data {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
#[derive(Eq)]
pub struct DataSlice(Vec<Data>);
impl DataSlice {
pub fn new(txs: &[Data]) -> Self {
DataSlice(Vec::from(txs))
}
}
impl Ord for DataSlice {
fn cmp(&self, other: &DataSlice) -> Ordering {
self.0.cmp(&other.0)
}
}
impl PartialOrd for DataSlice {
fn partial_cmp(&self, other: &DataSlice) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for DataSlice {
fn eq(&self, other: &DataSlice) -> bool {
self.cmp(other) == Ordering::Equal
}
}
#[test]
fn test_sort() {
let d1 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]);
let d2 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]);
assert!(d1 == d2);
let d1 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]);
let d2 = <Vec<u8>>::from([0x01, 0x00, 0x00, 0x00, 0x00]);
assert!(d1 < d2);
let d1 = Data(<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]));
let d2 = Data(<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00, 0x00]));
assert!(d1 < d2);
let d1 = Data(<Vec<u8>>::from([0x99, 0x00, 0x00, 0x00]));
let d2 = Data(<Vec<u8>>::from([0x99, 0x00, 0x00, 0x00, 0x00]));
assert!(d1 < d2);
let d1 = Data(<Vec<u8>>::from([0x99, 0x00, 0x00]));
let d2 = Data(<Vec<u8>>::from([0x99, 0x00, 0x01]));
assert!(d1 < d2);
let d1 = Data(<Vec<u8>>::from([0x99, 0x01, 0x01]));
let d2 = Data(<Vec<u8>>::from([0x99, 0x20, 0x01]));
assert!(d1 > d2);
let d1 = Data(<Vec<u8>>::from([0x01]));
let d2 = Data(<Vec<u8>>::from([0x02]));
let d3 = Data(<Vec<u8>>::from([0x03]));
assert!(d1 < d2);
assert!(d2 > d3);
assert!(d1 > d3);
let mut ds1 = DataSlice(vec![
Data(<Vec<u8>>::from([0x01])),
Data(<Vec<u8>>::from([0x02])),
Data(<Vec<u8>>::from([0x03])),
]);
ds1.0.sort();
let ds2 = DataSlice(vec![
Data(<Vec<u8>>::from([0x03])),
Data(<Vec<u8>>::from([0x01])),
Data(<Vec<u8>>::from([0x02])),
]);
assert!(ds1 == ds2);
let mut ds1 = vec![
Data(<Vec<u8>>::from([0x01])),
Data(<Vec<u8>>::from([0x02])),
Data(<Vec<u8>>::from([0x03])),
];
ds1.sort();
let ds2 = vec![
Data(<Vec<u8>>::from([0x03])),
Data(<Vec<u8>>::from([0x01])),
Data(<Vec<u8>>::from([0x02])),
];
assert!(ds1 == ds2);
let mut ds1 = vec![
<Vec<u8>>::from([0x01]),
<Vec<u8>>::from([0x02]),
<Vec<u8>>::from([0x03]),
];
ds1.sort_by(|a, b| (Data::from_slice(a.as_ref())).cmp(&Data::from_slice(b.as_ref())));
let ds2 = vec![
<Vec<u8>>::from([0x03]),
<Vec<u8>>::from([0x01]),
<Vec<u8>>::from([0x02]),
];
assert!(ds1 == ds2);
}