use std::collections::HashMap;
use crate::cluster::capability::registry::{CapabilityAd, CapabilityRegistry};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct NegotiatedCapabilities {
chosen: HashMap<String, Vec<u8>>,
}
impl NegotiatedCapabilities {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, name: String, value: Vec<u8>) {
self.chosen.insert(name, value);
}
#[must_use]
pub fn get(&self, name: &str) -> Option<&[u8]> {
self.chosen.get(name).map(Vec::as_slice)
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.chosen.is_empty()
}
#[must_use]
pub fn len(&self) -> usize {
self.chosen.len()
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &Vec<u8>)> {
self.chosen.iter()
}
}
pub(crate) fn negotiate_with_floor(
registry: &CapabilityRegistry,
peer_ad: &CapabilityAd,
) -> NegotiatedCapabilities {
let slots = registry.slots_for_negotiation();
let mut peer_by_name: HashMap<&str, &[Vec<u8>]> =
HashMap::with_capacity(peer_ad.entries().len());
for entry in peer_ad.entries() {
peer_by_name.insert(entry.name(), entry.supported());
}
let mut out = NegotiatedCapabilities::new();
for (name, slot) in slots {
let chosen = if let Some(peer_supported) = peer_by_name.get(name) {
match slot.merge_bytes(peer_supported) {
Some(v) => v,
None => slot.floor_bytes().to_vec(),
}
} else {
slot.floor_bytes().to_vec()
};
out.insert((*name).to_string(), chosen);
}
out
}