pub use super::{
bucket::{
AppliedPending, ConnectionState, InsertResult, Node, NodeStatus, MAX_NODES_PER_BUCKET,
},
key::*,
ConnectionDirection,
};
use super::*;
pub struct EntryRefView<'a, TPeerId, TVal: Eq> {
pub node: NodeRefView<'a, TPeerId, TVal>,
pub status: NodeStatus,
}
pub struct NodeRefView<'a, TPeerId, TVal: Eq> {
pub key: &'a Key<TPeerId>,
pub value: &'a TVal,
}
#[derive(Clone, Debug)]
pub struct EntryView<TPeerId, TVal: Eq> {
pub node: Node<TPeerId, TVal>,
pub status: NodeStatus,
}
impl<TPeerId, TVal: Eq> AsRef<Key<TPeerId>> for EntryView<TPeerId, TVal> {
fn as_ref(&self) -> &Key<TPeerId> {
&self.node.key
}
}
#[derive(Debug)]
#[allow(clippy::enum_variant_names)]
pub enum Entry<'a, TPeerId, TVal: Eq> {
Present(PresentEntry<'a, TPeerId, TVal>, NodeStatus),
Pending(PendingEntry<'a, TPeerId, TVal>, NodeStatus),
Absent(AbsentEntry<'a, TPeerId, TVal>),
SelfEntry,
}
#[derive(Debug)]
struct EntryRef<'a, TPeerId, TVal: Eq> {
bucket: &'a mut KBucket<TPeerId, TVal>,
key: &'a Key<TPeerId>,
}
impl<'a, TPeerId, TVal> Entry<'a, TPeerId, TVal>
where
TPeerId: Clone,
TVal: Eq,
{
pub(super) fn new(bucket: &'a mut KBucket<TPeerId, TVal>, key: &'a Key<TPeerId>) -> Self {
if let Some(pos) = bucket.position(key) {
let status = bucket.status(pos);
Entry::Present(PresentEntry::new(bucket, key), status)
} else if let Some(pending) = bucket.as_pending(key) {
let status = pending.status();
Entry::Pending(PendingEntry::new(bucket, key), status)
} else {
Entry::Absent(AbsentEntry::new(bucket, key))
}
}
}
#[derive(Debug)]
pub struct PresentEntry<'a, TPeerId, TVal: Eq>(EntryRef<'a, TPeerId, TVal>);
impl<'a, TPeerId, TVal> PresentEntry<'a, TPeerId, TVal>
where
TPeerId: Clone,
TVal: Eq,
{
fn new(bucket: &'a mut KBucket<TPeerId, TVal>, key: &'a Key<TPeerId>) -> Self {
PresentEntry(EntryRef { bucket, key })
}
pub fn value(&self) -> &TVal {
&self
.0
.bucket
.get(self.0.key)
.expect("We can only build a ConnectedEntry if the entry is in the bucket; QED")
.value
}
pub fn update(
self,
state: ConnectionState,
direction: Option<ConnectionDirection>,
) -> Result<Self, FailureReason> {
match self.0.bucket.update_status(self.0.key, state, direction) {
UpdateResult::Failed(reason) => Err(reason),
UpdateResult::UpdatedAndPromoted
| UpdateResult::Updated
| UpdateResult::UpdatedPending
| UpdateResult::NotModified => {
Ok(Self::new(self.0.bucket, self.0.key))
}
}
}
pub fn remove(self) {
self.0.bucket.remove(self.0.key);
}
}
#[derive(Debug)]
pub struct PendingEntry<'a, TPeerId, TVal: Eq>(EntryRef<'a, TPeerId, TVal>);
impl<'a, TPeerId, TVal: Eq> PendingEntry<'a, TPeerId, TVal>
where
TPeerId: Clone,
TVal: Eq,
{
fn new(bucket: &'a mut KBucket<TPeerId, TVal>, key: &'a Key<TPeerId>) -> Self {
PendingEntry(EntryRef { bucket, key })
}
pub fn value(&mut self) -> &mut TVal {
self.0
.bucket
.pending_mut()
.expect("We can only build a ConnectedPendingEntry if the entry is pending; QED")
.value_mut()
}
pub fn update(self, status: NodeStatus) -> PendingEntry<'a, TPeerId, TVal> {
self.0.bucket.update_pending(status);
PendingEntry::new(self.0.bucket, self.0.key)
}
pub fn remove(self) {
self.0.bucket.remove(self.0.key);
}
}
#[derive(Debug)]
pub struct AbsentEntry<'a, TPeerId, TVal: Eq>(EntryRef<'a, TPeerId, TVal>);
impl<'a, TPeerId, TVal> AbsentEntry<'a, TPeerId, TVal>
where
TPeerId: Clone,
TVal: Eq,
{
fn new(bucket: &'a mut KBucket<TPeerId, TVal>, key: &'a Key<TPeerId>) -> Self {
AbsentEntry(EntryRef { bucket, key })
}
pub fn insert(self, value: TVal, status: NodeStatus) -> InsertResult<TPeerId> {
self.0.bucket.insert(Node {
key: self.0.key.clone(),
value,
status,
})
}
}