use rand::random;
use serde::{Deserialize, Serialize};
use sha2::digest::{consts::U32, generic_array::GenericArray};
use std::num::ParseIntError;
use std::{fmt, str::FromStr};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ParseError {
#[error("Give no more than 64 hexadecimal characters")]
HexTooLong,
#[error(transparent)]
ParseInt(#[from] ParseIntError),
}
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Hash)]
pub struct U256([u8; 32]);
impl fmt::Display for U256 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for index in 0..8 {
f.write_fmt(format_args!("{:02x}", self.0[index]))?;
}
Ok(())
}
}
impl AsRef<[u8]> for U256 {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl fmt::Debug for U256 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (index, byte) in self.0.iter().enumerate() {
if index % 8 == 0 && index > 0 {
f.write_str("-")?;
}
f.write_fmt(format_args!("{:02x}", byte))?;
}
Ok(())
}
}
impl U256 {
pub fn rnd() -> U256 {
U256 { 0: random() }
}
pub fn to_bytes(self) -> [u8; 32] {
self.0
}
}
impl FromStr for U256 {
type Err = ParseError;
fn from_str(s: &str) -> Result<U256, ParseError> {
if s.len() > 64 {
return Err(ParseError::HexTooLong);
}
let v: Vec<u8> = (0..s.len())
.step_by(2)
.map(|i| u8::from_str_radix(&s[i..i + 2], 16))
.collect::<Result<Vec<u8>, ParseIntError>>()?;
let mut u = U256 { 0: [0u8; 32] };
v.iter().enumerate().for_each(|(i, b)| u.0[i] = *b);
Ok(u)
}
}
impl From<GenericArray<u8, U32>> for U256 {
fn from(ga: GenericArray<u8, U32>) -> Self {
let mut u = U256 { 0: [0u8; 32] };
ga.as_slice()
.iter()
.enumerate()
.for_each(|(i, b)| u.0[i] = *b);
u
}
}
impl From<[u8; 32]> for U256 {
fn from(b: [u8; 32]) -> Self {
U256 { 0: b }
}
}
pub type NodeID = U256;
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct NodeIDs(pub Vec<NodeID>);
impl NodeIDs {
pub fn new(nbr: u32) -> Self {
let mut ret = NodeIDs { 0: vec![] };
for _ in 0..nbr {
ret.0.push(NodeID::rnd())
}
ret
}
pub fn empty() -> Self {
NodeIDs::new(0)
}
pub fn slice(&self, from: usize, len: usize) -> Self {
NodeIDs {
0: self.0[from..(from + len)].to_vec(),
}
}
pub fn remove_missing(&mut self, nodes: &NodeIDs) -> NodeIDs {
self.remove(nodes, false)
}
pub fn remove_existing(&mut self, nodes: &NodeIDs) -> NodeIDs {
self.remove(nodes, true)
}
pub fn contains_any(&self, other: &NodeIDs) -> bool {
for node in &self.0 {
for node_other in &other.0 {
if node == node_other {
return true;
}
}
}
false
}
fn remove(&mut self, nodes: &NodeIDs, exists: bool) -> NodeIDs {
let mut ret = vec![];
let mut i = 0;
while i < self.0.len() {
if nodes.0.contains(&self.0[i]) == exists {
ret.push(self.0.remove(i));
} else {
i += 1;
}
}
NodeIDs(ret)
}
}
impl From<Vec<U256>> for NodeIDs {
fn from(nodes: Vec<U256>) -> Self {
Self { 0: nodes }
}
}
impl From<&Vec<U256>> for NodeIDs {
fn from(nodes: &Vec<U256>) -> Self {
Self {
0: nodes.to_vec(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::fmt::Error;
#[test]
fn test_new_nodes() -> Result<(), Error> {
let mut nodes = NodeIDs::new(4);
let nodes2 = nodes.remove_missing(&NodeIDs::new(0));
assert_eq!(0, nodes.0.len());
assert_eq!(4, nodes2.0.len());
Ok(())
}
}