btpeer 0.9.0

Simple CLI tool and library to get peers from TCP/HTTP and UDP BitTorrent trackers
Documentation
use anyhow::Result;
use cyphernet::addr::{HostName, PartialAddr, i2p::I2pAddr};
use std::{
    net::{IpAddr, Ipv4Addr, Ipv6Addr},
    str::FromStr,
};

pub type Peer = PartialAddr<HostName, 0>;

#[derive(Debug, Default)]
pub struct Buffer(pub Vec<Peer>);

impl Buffer {
    pub fn from_peers6(ip_port_chunks: &[u8]) -> Result<Self> {
        const L: usize = 18;
        let mut b = Vec::with_capacity(ip_port_chunks.len() / L);
        for chunk in ip_port_chunks.chunks_exact(L) {
            let ip_bytes: [u8; 16] = chunk[0..16].try_into()?;
            b.push(PartialAddr {
                host: HostName::Ip(IpAddr::V6(Ipv6Addr::from(ip_bytes))),
                port: Some(u16::from_be_bytes(chunk[16..L].try_into()?)),
            })
        }
        Ok(Self(b))
    }
    pub fn from_peers(ip_port_chunks: &[u8]) -> Result<Self> {
        const L: usize = 6;
        let mut b = Vec::with_capacity(ip_port_chunks.len() / L);
        for chunk in ip_port_chunks.chunks_exact(L) {
            let ip_bytes: [u8; 4] = chunk[0..4].try_into()?;
            b.push(PartialAddr {
                host: HostName::Ip(IpAddr::V4(Ipv4Addr::from(ip_bytes))),
                port: Some(u16::from_be_bytes(chunk[4..L].try_into()?)),
            })
        }
        Ok(Self(b))
    }
    pub fn from_peers_i2p(host_chunks: &[u8]) -> Result<Self> {
        const L: usize = 32;
        let mut b = Vec::with_capacity(host_chunks.len() / L);
        for chunk in host_chunks.chunks_exact(L) {
            b.push(PartialAddr {
                host: HostName::I2p(I2pAddr::from_str(&format!(
                    "{}.b32.i2p",
                    data_encoding::BASE32_NOPAD.encode(chunk)
                ))?),
                port: None,
            })
        }
        Ok(Self(b))
    }
}