rlibbencode 0.1.0

Rust Bencode library
Documentation
use std::any::Any;
use std::{fmt, io};
use std::fmt::Formatter;
use crate::variables::bencode_bytes::BencodeBytes;
use crate::variables::bencode_number::BencodeNumber;
use crate::variables::bencode_object::BencodeObject;
use crate::variables::inter::bencode_types::BencodeTypes;
use crate::variables::inter::bencode_variable::{BencodeVariable, FromBencode, ToBencode};

pub trait AddArray<V> {

    fn push(&mut self, value: V);

    fn insert(&mut self, index: usize, value: V);
}

#[derive(Debug, Clone)]
pub struct BencodeArray {
    value: Vec<Box<dyn BencodeVariable>>
}

impl BencodeArray {

    pub fn new() -> Self {
        Self {
            value: Vec::new()
        }
    }

    pub fn get<V: BencodeVariable + 'static>(&self, index: usize) -> Option<&V> {
        self.value
            .get(index)?
            .as_any()
            .downcast_ref::<V>()
    }

    pub fn get_mut<V: BencodeVariable + 'static>(&mut self, index: usize) -> Option<&mut V> {
        self.value
            .get_mut(index)?
            .as_any_mut()
            .downcast_mut::<V>()
    }

    fn remove(&mut self, index: usize) -> Box<dyn BencodeVariable> {
        self.value.remove(index)
    }

    pub fn len(&self) -> usize {
        self.value.len()
    }

    pub fn iter(&self) -> impl Iterator<Item = &Box<dyn BencodeVariable>> {
        self.value.iter()
    }
}

impl BencodeVariable for BencodeArray {

    fn get_type(&self) -> BencodeTypes {
        BencodeTypes::Array
    }

    fn upcast(self) -> Box<dyn BencodeVariable> {
        Box::new(self)
    }

    fn as_any(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }

    fn clone_box(&self) -> Box<dyn BencodeVariable> {
        Box::new(self.clone())
    }
}

impl ToBencode for BencodeArray {

    fn to_bencode(&self) -> Vec<u8> {
        let mut buf = vec![BencodeTypes::Array.prefix()];
        for e in &self.value {
            buf.extend(e.to_bencode());
        }
        buf.push(BencodeTypes::Array.suffix());
        buf
    }
}

impl FromBencode for BencodeArray {

    fn from_bencode_with_offset(buf: &[u8]) -> io::Result<(Self, usize)> {
        if !BencodeTypes::from_code(buf[0]).eq(&BencodeTypes::Array) {
            return Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid prefix for object"));
        }

        let mut value = Vec::new();

        let mut off = 1;
        while buf[off] != BencodeTypes::Array.suffix() {
            let (v, l) = match BencodeTypes::from_code(buf[off]) {
                BencodeTypes::Array => {
                    let (v, l) = BencodeArray::from_bencode_with_offset(&buf[off..])?;
                    (v.upcast(), l)
                }
                BencodeTypes::Object => {
                    let (v, l) = BencodeObject::from_bencode_with_offset(&buf[off..])?;
                    (v.upcast(), l)
                }
                BencodeTypes::Number => {
                    let (v, l) = BencodeNumber::from_bencode_with_offset(&buf[off..])?;
                    (v.upcast(), l)
                }
                BencodeTypes::Bytes => {
                    let (v, l) = BencodeBytes::from_bencode_with_offset(&buf[off..])?;
                    (v.upcast(), l)
                }
            };

            off += l;
            value.push(v);
        }

        Ok((Self {
            value
        }, off + 1))
    }
}

macro_rules! impl_bencode_add_array {
    ($(($_type:ty, $value:ty)),*) => {
        $(
            impl AddArray<$value> for BencodeArray {

                fn push(&mut self, value: $value) {
                    self.value.push(Box::new(<$_type>::from(value)));
                }

                fn insert(&mut self, index: usize, value: $value) {
                    self.value.insert(index, Box::new(<$_type>::from(value)));
                }
            }
        )*
    };
}

impl_bencode_add_array!(
    (BencodeNumber, u8),
    (BencodeNumber, u16),
    (BencodeNumber, u32),
    (BencodeNumber, u64),
    (BencodeNumber, u128),
    (BencodeNumber, usize),
    (BencodeNumber, i8),
    (BencodeNumber, i16),
    (BencodeNumber, i32),
    (BencodeNumber, i64),
    (BencodeNumber, i128),
    (BencodeNumber, isize),
    (BencodeNumber, f32),
    (BencodeNumber, f64),

    (BencodeBytes, String),
    (BencodeBytes, &str),
    (BencodeBytes, Vec<u8>),
    (BencodeBytes, &Vec<u8>),
    (BencodeBytes, &[u8])
);

impl<const N: usize> AddArray<[u8; N]> for BencodeArray {

    fn push(&mut self, value: [u8; N]) {
        self.value.push(Box::new(BencodeBytes::from(value)));
    }

    fn insert(&mut self, index: usize, value: [u8; N]) {
        self.value.insert(index, Box::new(BencodeBytes::from(value)));
    }
}

impl AddArray<BencodeObject> for BencodeArray {

    fn push(&mut self, value: BencodeObject) {
        self.value.push(Box::new(value));
    }

    fn insert(&mut self, index: usize, value: BencodeObject) {
        self.value.insert(index, Box::new(value));
    }
}

impl AddArray<BencodeArray> for BencodeArray {

    fn push(&mut self, value: BencodeArray) {
        self.value.push(Box::new(value));
    }

    fn insert(&mut self, index: usize, value: BencodeArray) {
        self.value.insert(index, Box::new(value));
    }
}

impl AddArray<Box<dyn BencodeVariable>> for BencodeArray {

    fn push(&mut self, value: Box<dyn BencodeVariable>) {
        self.value.push(value);
    }

    fn insert(&mut self, index: usize, value: Box<dyn BencodeVariable>) {
        self.value.insert(index, value);
    }
}

impl PartialEq for BencodeArray {

    fn eq(&self, other: &Self) -> bool {
        if self.value.len() != other.value.len() {
            return false;
        }

        for (a, b) in self.value.iter().zip(other.value.iter()) {
            if a.get_type() != b.get_type() {
                return false;
            }

            if !match a.get_type() {
                BencodeTypes::Object => a.as_any().downcast_ref::<BencodeObject>().unwrap().eq(
                    b.as_any().downcast_ref::<BencodeObject>().unwrap()),
                BencodeTypes::Array => a.as_any().downcast_ref::<BencodeArray>().unwrap().eq(
                        b.as_any().downcast_ref::<BencodeArray>().unwrap()),
                BencodeTypes::Number => a.as_any().downcast_ref::<BencodeNumber>().unwrap().eq(
                    b.as_any().downcast_ref::<BencodeNumber>().unwrap()),
                BencodeTypes::Bytes => a.as_any().downcast_ref::<BencodeBytes>().unwrap().eq(
                    b.as_any().downcast_ref::<BencodeBytes>().unwrap()),
            } {
                return false;
            }
        }

        true
    }
}

impl fmt::Display for BencodeArray {

    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "[\r\n")?;

        for val in &self.value {
            writeln!(f, "{}\r", match val.get_type() {
                BencodeTypes::Number => format!("\t\u{001b}[0;33m{}\u{001b}[0m", val),
                BencodeTypes::Bytes => format!("\t\u{001b}[0;34m{}\u{001b}[0m", val),
                BencodeTypes::Array | BencodeTypes::Object => {
                    let val = format!("{}", val).replace("\r\n", "\r\n\t");
                    format!("\t{}", val)
                }
            })?;
        }

        write!(f, "]")
    }
}