use std::fmt;
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
bitflags! {
#[derive(Serialize, Deserialize, Clone, Copy, Debug, Eq, PartialEq)]
pub struct PeerFeatures: u32 {
const NONE = 0b0000_0000;
const MESSAGE_PROPAGATION = 0b0000_0001;
const DHT_STORE_FORWARD = 0b0000_0010;
const COMMUNICATION_NODE = Self::MESSAGE_PROPAGATION.bits() | Self::DHT_STORE_FORWARD.bits();
const COMMUNICATION_CLIENT = Self::NONE.bits();
}
}
const UNKNOWN_PEER_FEATURE: i32 = -1;
impl PeerFeatures {
#[inline]
pub fn is_client(self) -> bool {
self == PeerFeatures::COMMUNICATION_CLIENT
}
#[inline]
pub fn is_node(self) -> bool {
self == PeerFeatures::COMMUNICATION_NODE
}
pub fn as_role_str(self) -> &'static str {
match self {
PeerFeatures::COMMUNICATION_NODE => "node",
PeerFeatures::COMMUNICATION_CLIENT => "client",
_ => "unknown",
}
}
pub fn to_i32(&self) -> i32 {
match *self {
PeerFeatures::MESSAGE_PROPAGATION => 1,
PeerFeatures::DHT_STORE_FORWARD => 2,
PeerFeatures::COMMUNICATION_NODE => 3,
PeerFeatures::COMMUNICATION_CLIENT => 0,
_ => UNKNOWN_PEER_FEATURE, }
}
}
impl Default for PeerFeatures {
fn default() -> Self {
PeerFeatures::NONE
}
}
impl fmt::Display for PeerFeatures {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_i32_conversion() {
for feature in PeerFeatures::all() {
assert_ne!(
feature.to_i32(),
UNKNOWN_PEER_FEATURE,
"Failed for feature: {feature:?}",
);
match feature {
PeerFeatures::NONE => assert_eq!(feature.to_i32(), 0),
PeerFeatures::MESSAGE_PROPAGATION => assert_eq!(feature.to_i32(), 1),
PeerFeatures::DHT_STORE_FORWARD => assert_eq!(feature.to_i32(), 2),
PeerFeatures::COMMUNICATION_NODE => assert_eq!(feature.to_i32(), 3),
_ => panic!("Unexpected feature: {feature:?}"),
}
}
}
}