use crate::{Address, Id, Logs, Proximity, Record, Subscription, Subscriptions};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct NodeInfo {
id: Id,
address: Option<Address>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct NodeProfile {
info: NodeInfo,
subscriptions: Subscriptions,
}
pub struct NodeProfileBuilder {
id: Id,
address: Option<Address>,
subscriptions: Subscriptions,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Node {
profile: NodeProfile,
logs: Logs,
record: Record,
}
impl NodeInfo {
pub fn id(&self) -> &Id {
&self.id
}
pub fn address(&self) -> Option<&Address> {
self.address.as_ref()
}
}
impl NodeProfileBuilder {
pub fn new() -> Self {
Self {
id: Id::generate(rand::thread_rng()),
address: None,
subscriptions: Subscriptions::default(),
}
}
pub fn id(&mut self, id: Id) -> &mut Self {
self.id = id;
self
}
pub fn address(&mut self, address: Address) -> &mut Self {
self.address = Some(address);
self
}
pub fn add_subscription(&mut self, subscription: Subscription) -> &mut Self {
self.subscriptions.insert(subscription);
self
}
pub fn build(&self) -> NodeProfile {
NodeProfile {
info: NodeInfo {
id: self.id,
address: self.address.clone(),
},
subscriptions: self.subscriptions.clone(),
}
}
}
impl NodeProfile {
pub(crate) fn info(&self) -> &NodeInfo {
&self.info
}
pub fn id(&self) -> &Id {
&self.info.id
}
pub fn address(&self) -> Option<&Address> {
self.info.address.as_ref()
}
pub fn subscriptions(&self) -> &Subscriptions {
&self.subscriptions
}
pub fn common_subscriptions<'a>(
&'a self,
other: &'a Self,
) -> impl Iterator<Item = &'a Subscription> {
self.subscriptions
.common_subscriptions(&other.subscriptions)
}
pub fn proximity(&self, other: &Self) -> Proximity {
self.subscriptions.proximity_to(&other.subscriptions)
}
pub fn check(&self) -> bool {
true
}
}
impl Node {
pub(crate) fn new(profile: NodeProfile) -> Self {
Self {
profile,
logs: Logs::default(),
record: Record::default(),
}
}
pub(crate) fn info(&self) -> &NodeInfo {
&self.profile().info()
}
pub fn address(&self) -> Option<&Address> {
self.profile().address()
}
pub fn id(&self) -> &Id {
self.profile().id()
}
pub fn profile(&self) -> &NodeProfile {
&self.profile
}
pub(crate) fn update_gossip(&mut self, gossip: NodeProfile) {
self.update_profile(gossip);
self.logs_mut().updated();
}
fn update_profile(&mut self, profile: NodeProfile) {
self.profile = profile;
}
pub fn record(&self) -> &Record {
&self.record
}
pub fn record_mut(&mut self) -> &mut Record {
&mut self.record
}
pub fn logs(&self) -> &Logs {
&self.logs
}
pub fn logs_mut(&mut self) -> &mut Logs {
&mut self.logs
}
}
impl Default for NodeProfileBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod test {
use super::*;
use quickcheck::{Arbitrary, Gen};
impl Arbitrary for NodeInfo {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
NodeInfo {
id: Id::arbitrary(g),
address: Arbitrary::arbitrary(g),
}
}
}
impl Arbitrary for NodeProfile {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
NodeProfile {
info: NodeInfo::arbitrary(g),
subscriptions: Subscriptions::arbitrary(g),
}
}
}
#[quickcheck]
fn node_info_encode_decode_json(node_info: NodeInfo) -> bool {
let encoded = serde_json::to_string(&node_info).unwrap();
let decoded = serde_json::from_str(&encoded).unwrap();
node_info == decoded
}
#[quickcheck]
fn node_info_encode_decode_bincode(node_info: NodeInfo) -> bool {
let encoded = bincode::serialize(&node_info).unwrap();
let decoded = bincode::deserialize(&encoded).unwrap();
node_info == decoded
}
#[quickcheck]
fn node_profile_encode_decode_json(node_profile: NodeProfile) -> bool {
let encoded = serde_json::to_string(&node_profile).unwrap();
let decoded = serde_json::from_str(&encoded).unwrap();
node_profile == decoded
}
#[quickcheck]
fn node_profile_encode_decode_bincode(node_profile: NodeProfile) -> bool {
let encoded = bincode::serialize(&node_profile).unwrap();
let decoded = bincode::deserialize(&encoded).unwrap();
node_profile == decoded
}
}