use crate::{peer::Peer, Prefix, XorName};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::{
borrow::Borrow,
collections::BTreeMap,
fmt::{self, Debug, Display, Formatter},
};
#[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
pub struct EldersInfo {
pub elders: BTreeMap<XorName, Peer>,
pub prefix: Prefix,
}
impl EldersInfo {
pub fn new<I>(elders: I, prefix: Prefix) -> Self
where
I: IntoIterator<Item = Peer>,
{
Self {
elders: elders
.into_iter()
.map(|peer| (*peer.name(), peer))
.collect(),
prefix,
}
}
pub(crate) fn peers(
&self,
) -> impl Iterator<Item = &Peer> + DoubleEndedIterator + ExactSizeIterator + Clone {
self.elders.values()
}
pub(crate) fn position(&self, name: &XorName) -> Option<usize> {
self.elders.keys().position(|other_name| other_name == name)
}
}
impl Borrow<Prefix> for EldersInfo {
fn borrow(&self) -> &Prefix {
&self.prefix
}
}
impl Debug for EldersInfo {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
write!(
formatter,
"EldersInfo {{ prefix: ({:b}), elders: {{{:?}}} }}",
self.prefix,
self.elders.values().format(", "),
)
}
}
impl Display for EldersInfo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"{{{}}}/({:b})",
self.elders.keys().format(", "),
self.prefix,
)
}
}
#[cfg(test)]
pub(crate) mod test_utils {
use super::EldersInfo;
use crate::{crypto, node::Node, MIN_AGE};
use itertools::Itertools;
use std::{cell::Cell, net::SocketAddr};
use xor_name::Prefix;
pub(crate) fn gen_addr() -> SocketAddr {
thread_local! {
static NEXT_PORT: Cell<u16> = Cell::new(1000);
}
let port = NEXT_PORT.with(|cell| cell.replace(cell.get().wrapping_add(1)));
([192, 0, 2, 0], port).into()
}
pub(crate) fn gen_sorted_nodes(count: usize) -> Vec<Node> {
(0..count)
.map(|_| Node::new(crypto::gen_keypair(), gen_addr()).with_age(MIN_AGE + 1))
.sorted_by_key(|node| node.name())
.collect()
}
pub(crate) fn gen_elders_info(prefix: Prefix, count: usize) -> (EldersInfo, Vec<Node>) {
let nodes = gen_sorted_nodes(count);
let elders = nodes
.iter()
.map(Node::peer)
.map(|peer| (*peer.name(), peer))
.collect();
let elders_info = EldersInfo { elders, prefix };
(elders_info, nodes)
}
}