use std::hash::Hash as StdHash;
use std::time::{SystemTime, UNIX_EPOCH};
use p2panda_core::VerifyingKey;
use rand::RngExt;
use rand_chacha::ChaCha20Rng;
use serde::{Deserialize, Serialize};
use crate::address_book::traits::NodeInfo;
pub type TestNodeId = VerifyingKey;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, StdHash, Serialize, Deserialize)]
pub struct TestNodeInfo {
pub id: TestNodeId,
pub bootstrap: bool,
pub transports: Option<TestTransportInfo>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, StdHash, Serialize, Deserialize)]
pub struct TestTransportInfo {
address: String,
timestamp: u64,
}
impl TestTransportInfo {
pub fn new(address: &str) -> Self {
Self {
address: address.to_owned(),
timestamp: current_timestamp(),
}
}
}
impl TestNodeInfo {
pub fn new(id: TestNodeId) -> Self {
Self {
id,
bootstrap: false,
transports: None,
}
}
pub fn new_bootstrap(id: TestNodeId) -> Self {
Self {
id,
bootstrap: true,
transports: None,
}
}
pub fn with_random_address(mut self, rng: &mut ChaCha20Rng) -> Self {
self.transports = Some(TestTransportInfo {
timestamp: current_timestamp(),
address: {
let segments: [u8; 4] = rng.random();
segments.map(|s| s.to_string()).join(".")
},
});
self
}
pub fn update_transports(&mut self, transports: TestTransportInfo) -> bool {
match self.transports {
Some(ref current) => {
if current.timestamp < transports.timestamp {
self.transports = Some(transports);
return true;
}
}
None => {
self.transports = Some(transports);
return true;
}
}
false
}
}
impl NodeInfo<TestNodeId> for TestNodeInfo {
type Transports = TestTransportInfo;
fn id(&self) -> TestNodeId {
self.id
}
fn is_bootstrap(&self) -> bool {
self.bootstrap
}
fn is_stale(&self) -> bool {
false
}
fn transports(&self) -> Option<Self::Transports> {
self.transports.clone()
}
}
pub fn current_timestamp() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system clock is not behind")
.as_secs()
}