mod negotiator;
mod registry;
pub use self::negotiator::NegotiatedCapabilities;
pub use self::registry::{
Capability, CapabilityAd, CapabilityAdEntry, CapabilityCodecError, CapabilityRegistry,
};
pub const CAP_DNODE_FRAMING_VERSION: &str = "dnode_framing_version";
pub const CAP_AAE_TREE_FORMAT: &str = "aae_tree_format";
pub const CAP_CRDT_OBJECT_FORMAT: &str = "crdt_object_format";
pub const CAP_GOSSIP_PHI_NEGOTIABLE: &str = "gossip_phi_threshold_negotiable";
pub struct DnodeFramingVersion;
impl Capability for DnodeFramingVersion {
type Value = u32;
fn name(&self) -> &'static str {
CAP_DNODE_FRAMING_VERSION
}
fn supported_values(&self) -> Vec<u32> {
vec![1, 2]
}
fn merge(&self, peer: &[u32]) -> Option<u32> {
self.supported_values()
.into_iter()
.filter(|v| peer.contains(v))
.max()
}
fn encode_value(&self, v: &u32) -> Vec<u8> {
v.to_le_bytes().to_vec()
}
fn decode_value(&self, b: &[u8]) -> Option<u32> {
<[u8; 4]>::try_from(b).ok().map(u32::from_le_bytes)
}
}
pub struct AaeTreeFormat;
impl Capability for AaeTreeFormat {
type Value = u32;
fn name(&self) -> &'static str {
CAP_AAE_TREE_FORMAT
}
fn supported_values(&self) -> Vec<u32> {
vec![1]
}
fn merge(&self, peer: &[u32]) -> Option<u32> {
self.supported_values()
.into_iter()
.filter(|v| peer.contains(v))
.max()
}
fn encode_value(&self, v: &u32) -> Vec<u8> {
v.to_le_bytes().to_vec()
}
fn decode_value(&self, b: &[u8]) -> Option<u32> {
<[u8; 4]>::try_from(b).ok().map(u32::from_le_bytes)
}
}
pub struct CrdtObjectFormat;
impl Capability for CrdtObjectFormat {
type Value = u32;
fn name(&self) -> &'static str {
CAP_CRDT_OBJECT_FORMAT
}
fn supported_values(&self) -> Vec<u32> {
vec![1]
}
fn merge(&self, peer: &[u32]) -> Option<u32> {
self.supported_values()
.into_iter()
.filter(|v| peer.contains(v))
.max()
}
fn encode_value(&self, v: &u32) -> Vec<u8> {
v.to_le_bytes().to_vec()
}
fn decode_value(&self, b: &[u8]) -> Option<u32> {
<[u8; 4]>::try_from(b).ok().map(u32::from_le_bytes)
}
}
pub struct GossipPhiNegotiable;
impl Capability for GossipPhiNegotiable {
type Value = bool;
fn name(&self) -> &'static str {
CAP_GOSSIP_PHI_NEGOTIABLE
}
fn supported_values(&self) -> Vec<bool> {
vec![false, true]
}
fn merge(&self, peer: &[bool]) -> Option<bool> {
if self.supported_values().contains(&true) && peer.contains(&true) {
Some(true)
} else if self.supported_values().contains(&false) && peer.contains(&false) {
Some(false)
} else {
None
}
}
fn encode_value(&self, v: &bool) -> Vec<u8> {
vec![u8::from(*v)]
}
fn decode_value(&self, b: &[u8]) -> Option<bool> {
match b {
[0] => Some(false),
[1] => Some(true),
_ => None,
}
}
}
#[must_use]
pub fn default_registry() -> CapabilityRegistry {
let mut reg = CapabilityRegistry::new();
reg.register(DnodeFramingVersion);
reg.register(AaeTreeFormat);
reg.register(CrdtObjectFormat);
reg.register(GossipPhiNegotiable);
reg
}