use std::{collections::HashMap, ops::RangeInclusive};
use candid::Principal;
use rangemap::RangeInclusiveSet;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SubnetType {
System,
Application,
VerifiedApplication,
CloudEngine,
Unknown(String),
}
#[derive(Debug, Clone)]
pub struct Subnet {
pub(crate) id: Principal,
pub(crate) key: Vec<u8>,
pub(crate) node_keys: HashMap<Principal, Vec<u8>>,
pub(crate) canister_ranges: RangeInclusiveSet<Principal>,
pub(crate) subnet_type: Option<SubnetType>,
}
impl Subnet {
pub fn contains_canister(&self, canister_id: &Principal) -> bool {
self.canister_ranges.contains(canister_id)
}
pub fn iter_canister_ranges(&self) -> CanisterRangesIter<'_> {
CanisterRangesIter {
inner: self.canister_ranges.iter(),
}
}
pub fn self_reported_key(&self) -> &[u8] {
&self.key
}
pub fn contains_node(&self, node_id: &Principal) -> bool {
self.node_keys.contains_key(node_id)
}
pub fn get_node_key(&self, node_id: &Principal) -> Option<&[u8]> {
self.node_keys.get(node_id).map(|k| &k[..])
}
pub fn iter_nodes(&self) -> SubnetNodeIter<'_> {
SubnetNodeIter {
inner: self.node_keys.keys(),
}
}
pub fn iter_node_keys(&self) -> SubnetKeysIter<'_> {
SubnetKeysIter {
inner: self.node_keys.iter(),
}
}
pub fn id(&self) -> Principal {
self.id
}
pub fn subnet_type(&self) -> Option<&SubnetType> {
self.subnet_type.as_ref()
}
}
pub struct CanisterRangesIter<'a> {
inner: rangemap::inclusive_set::Iter<'a, Principal>,
}
impl Iterator for CanisterRangesIter<'_> {
type Item = RangeInclusive<Principal>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().cloned()
}
}
#[derive(Debug)]
pub struct SubnetNodeIter<'a> {
inner: std::collections::hash_map::Keys<'a, Principal, Vec<u8>>,
}
impl<'a> Iterator for SubnetNodeIter<'a> {
type Item = Principal;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().copied()
}
}
#[derive(Debug)]
pub struct SubnetKeysIter<'a> {
inner: std::collections::hash_map::Iter<'a, Principal, Vec<u8>>,
}
impl<'a> Iterator for SubnetKeysIter<'a> {
type Item = (Principal, &'a [u8]);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(k, v)| (*k, &v[..]))
}
}