nardol 0.0.3

Simple framework that provides structure to data sent and received from network.
Documentation
mod from_bytes;
mod into_bytes;

use serde::{Deserialize, Serialize};

use std::iter::FromIterator;
use std::ops::Index;
use std::slice::SliceIndex;

use crate::ron::{FromRon, ToRon};

/// Wrapper around [Vec] of [u8] used to store data in form of bytes in this library.
// May be replaced with the bytes crate in the future.
#[derive(Default, Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct Bytes(Vec<u8>);

impl<Idx> Index<Idx> for Bytes
where
    Idx: SliceIndex<[u8]>,
{
    type Output = Idx::Output;

    fn index(&self, index: Idx) -> &Self::Output {
        &self.as_slice()[index]
    }
}

impl IntoIterator for Bytes {
    type Item = u8;

    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl FromIterator<u8> for Bytes {
    fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
        let mut bytes = Bytes::empty();

        for byte in iter {
            bytes.push(byte)
        }

        bytes
    }
}

impl std::fmt::Display for Bytes {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let string = String::from_utf8_lossy(&self.0).to_string();
        write!(f, "{}", string)
    }
}

impl FromRon<'_> for Bytes {}
impl ToRon for Bytes {}

impl Bytes {
    /// Creates a new [Bytes] from `content`.
    pub fn new(content: Vec<u8>) -> Self {
        Bytes(content)
    }

    /// Creates a new empty [Bytes].
    ///
    /// Usually declared as mutable and filled later.
    pub fn empty() -> Self {
        Bytes(Vec::new())
    }

    /// Pushes a new [u8] into [Bytes].
    ///
    /// Wrapper around [Vec::push].
    pub fn push(&mut self, value: u8) {
        self.0.push(value)
    }

    /// Returns an immutable [slice] of `bytes`.
    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }

    /// Returns an inner [Vec].
    ///
    /// [Vec] is cloned.
    pub fn vec(&self) -> Vec<u8> {
        self.0.clone()
    }

    /// Returns an reference to inner [Vec].
    pub fn vec_ref(&self) -> &Vec<u8> {
        &self.0
    }

    /// Returns an mutable reference to inner [Vec].
    pub fn vec_mut(&mut self) -> &mut Vec<u8> {
        &mut self.0
    }

    /// Takes an ownership of `self` and returns an inner [Vec].
    pub fn into_vec(self) -> Vec<u8> {
        self.0
    }

    /// Returns number of bytes inside `Self`.
    ///
    /// Wrapper around [Vec::len].
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns if `Self` is empty.
    ///
    /// Wrapper around [Vec::is_empty].
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Moves all elements of `other` into `Self`, leaving `other` empty.
    ///
    /// Wrapper around [Vec::append].
    pub fn append(&mut self, other: &mut Bytes) {
        self.0.append(other.vec_mut())
    }

    /// Returns [Some] with [u8] inside if there is a value on given `index`,
    /// otherwise returns [None].
    pub fn get(&self, index: usize) -> Option<u8> {
        let value = self.as_slice().get(index);
        value.copied()
    }

    /// Returns `indexes` on which provided pattern starts.
    pub fn find_pattern(&self, pattern: &Bytes) -> Option<Vec<usize>> {
        let pattern_slice = pattern.as_slice();
        let mut indexes: Option<Vec<usize>> = None;

        let mut i = 0;
        while i < self.len() {
            if self.get(i + pattern_slice.len()).is_none() {
                break;
            }

            let pattern_to_check = &self[i..i + pattern_slice.len()];

            if pattern_to_check == pattern_slice {
                match indexes {
                    Some(ref mut vec) => {
                        vec.push(i);
                    }
                    None => {
                        indexes = Some(vec![i]);
                    }
                }
                i += 4;
            } else {
                i += 1;
            }
        }
        indexes
    }

    /// Splits `self` at provided `pattern` which is not included in final result.
    pub fn split_at_pat(self, pattern: &Bytes) -> Vec<Bytes> {
        let mut split = Vec::new();

        let indexes = self.find_pattern(pattern);

        if indexes.is_none() {
            split.push(self);
            return split;
        }

        let indexes = indexes.unwrap();

        let mut part = Bytes::empty();

        let mut i = 0;
        while i < self.len() {
            if indexes.contains(&i) {
                split.push(part);
                part = Bytes::empty();
                i += pattern.len();
            }
            part.push(self[i]);

            i += 1;
        }

        if !part.is_empty() {
            split.push(part);
        }

        split
    }
}

#[test]
fn find_pattern_test() {
    let bytes = Bytes::from([1, 2, 3, 0, 0, 0, 0, 5, 6, 7, 0, 0, 0, 0, 8, 9, 10]);

    let indexes = bytes.find_pattern(&Bytes::from([0, 0, 0, 0]));

    println!("Result: {indexes:?}");

    assert_eq!(indexes, Some(vec![3, 10]));
}

#[test]
fn split_at_pat_test() {
    let bytes = Bytes::from([1, 2, 3, 0, 0, 0, 0, 5, 6, 7, 0, 0, 0, 0, 8, 9, 10]);

    let split = bytes.split_at_pat(&Bytes::from([0, 0, 0, 0]));

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

    assert_eq!(
        split,
        vec![
            Bytes::from([1, 2, 3]),
            Bytes::from([5, 6, 7]),
            Bytes::from([8, 9, 10])
        ]
    )
}