kbucket 0.1.0

Implementation of the kademlia k-bucket data structure as a tree
Documentation
use std::net;

type NodeLink = Option<Box<Node>>;

/// Main bucket tree data structure
#[derive(Debug)]
pub struct BucketTree {
    pub node_id: [u8; 64],
    pub root: Node,
}

/// Nodes in the tree can either be branches or leafs
#[derive(Debug)]
pub enum Node {
    BranchNode(BranchNode),
    LeafNode(LeafNode),
}

/// Branch nodes store references to either other branches or bucket nodes
#[derive(Debug)]
pub struct BranchNode {
    pub left: NodeLink,
    pub right: NodeLink,
}

/// Leaf nodes store the actual buckets
#[derive(Debug)]
pub struct LeafNode {
    pub can_split: bool,
    pub contacts: Vec<NodeInfo>,
}

/// Used to represent either IPv4 addresses or IPv6 addresses
#[derive(Debug)]
pub enum Address {
    V4(net::Ipv4Addr),
    V6(net::Ipv6Addr),
}

/// Used to store a noes ID and it's associated data
#[derive(Debug)]
pub struct NodeInfo {
    id: [u8; 64],
    ip: Address,
    port: u64,
}

impl BucketTree {
    /// Create a new bucket tree
    pub fn new(node_id: [u8; 64]) -> Self {
        BucketTree {
            node_id,
            root: Node::LeafNode(LeafNode {
                can_split: true,
                contacts: Vec::new(),
            }),
        }
    }

    /// Function to add node to the tree
    pub fn add(&mut self, node: &NodeInfo) {
        let mut current_node = &mut self.root;
        let mut bit_index = 0;

        // Walk the tree using the provided node id
        while let Node::BranchNode(x) = current_node {
            if bit_value(&node.id, bit_index) {
                current_node = x.right.as_mut().unwrap();
            } else {
                current_node = x.left.as_mut().unwrap();
            }
            bit_index += 1;
            continue;
        }

        println!("{:?}", current_node);
    }
}

impl LeafNode {
    /// Create a new leaf node
    #[allow(clippy::all)]
    pub fn new() -> Option<Box<Node>> {
        Some(Box::new(Node::LeafNode(LeafNode {
            can_split: true,
            contacts: Vec::new(),
        })))
    }
}

impl BranchNode {
    /// Create a new branch node
    #[allow(clippy::all)]
    pub fn new() -> Option<Box<Node>> {
        Some(Box::new(Node::BranchNode(BranchNode {
            left: None,
            right: None,
        })))
    }
}

impl NodeInfo {
    pub fn new(id: [u8; 64], ip: Address, port: u64) -> Self {
        NodeInfo { id, ip, port }
    }
}

// Find out if the value at a specific index is a 0 or 1
fn bit_value(key: &[u8; 64], bit_index: usize) -> bool {
    let byte_index = bit_index >> 3;
    let inner_bit_index = bit_index % 8;

    key[byte_index] & (1 << (7 - inner_bit_index)) >= 1
}