rlibdht 0.1.0

Rust DHT library
Documentation
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use crate::utils::uid::{ID_LENGTH, UID};
use super::net::address_types::{AddressTypes, IPV4_LENGTH, IPV6_LENGTH};
use super::node::Node;

pub fn pack_nodes(nodes: Vec<Node>, addr_type: AddressTypes) -> Vec<u8> {
    let addr_length = match addr_type {
        AddressTypes::Ipv4 => IPV4_LENGTH,
        AddressTypes::Ipv6 => IPV6_LENGTH
    };
    let mut buf = vec![0; nodes.len() * (ID_LENGTH + addr_length + 2)];
    let mut position = 0;

    for n in nodes {
        buf[position..position + ID_LENGTH].copy_from_slice(&n.uid.bid);
        position += ID_LENGTH;

        match n.address {
            SocketAddr::V4(ipv4) => {
                buf[position..position + addr_length].copy_from_slice(&ipv4.ip().octets());
            }
            SocketAddr::V6(ipv6) => {
                buf[position..position + addr_length].copy_from_slice(&ipv6.ip().octets());
            }
        }
        position += addr_length;

        buf[position] = (n.address.port() >> 8) as u8;
        buf[position + 1] = n.address.port() as u8;
        position += 2;
    }

    buf
}

pub fn unpack_nodes(buf: &[u8], addr_type: AddressTypes) -> Vec<Node> {
    let mut nodes = Vec::new();

    let addr_length = match addr_type {
        AddressTypes::Ipv4 => IPV4_LENGTH,
        AddressTypes::Ipv6 => IPV6_LENGTH
    };
    let mut position = 0;

    while position < buf.len() {
        if position + ID_LENGTH + addr_length + 2 > buf.len() {
            break;
        }

        let bid: [u8; ID_LENGTH] = buf[position..position + ID_LENGTH].try_into().expect("Slice with incorrect length");
        position += ID_LENGTH;

        let addr_bytes = &buf[position..position + addr_length];
        position += addr_length;

        let port = ((buf[position] as u16) << 8) | (buf[position + 1] as u16);
        position += 2;

        let address = match addr_type {
            AddressTypes::Ipv4 => {
                let octets: [u8; IPV4_LENGTH] = addr_bytes.try_into().expect("Slice with incorrect length");
                IpAddr::V4(Ipv4Addr::from(octets))
            },
            AddressTypes::Ipv6 => {
                let octets: [u8; IPV6_LENGTH] = addr_bytes.try_into().expect("Slice with incorrect length");
                IpAddr::V6(Ipv6Addr::from(octets))
            }
        };

        nodes.push(Node::new(UID::from(bid), SocketAddr::new(address, port)));
    }

    nodes
}