victorem 0.8.2

UPD Game Server Framework
Documentation
use crate::entities::{CommandPacket, Exception, StatePacket};
use std::collections::HashMap;

pub trait IWithId {
    fn get(&self) -> u32;
    fn set(&mut self, id: u32);
}

impl IWithId for StatePacket {
    fn get(&self) -> u32 {
        self.id
    }

    fn set(&mut self, id: u32) {
        self.id = id
    }
}

impl IWithId for CommandPacket {
    fn get(&self) -> u32 {
        self.id
    }

    fn set(&mut self, id: u32) {
        self.id = id
    }
}

pub struct Generator {
    id: u32,
}

impl Generator {
    pub fn new(start: u32) -> Generator {
        Generator { id: start }
    }
    pub fn generate(&mut self) -> u32 {
        let result = self.id;
        self.id += 1;
        result
    }
}

pub struct Filter {
    id: u32,
}

impl Filter {
    pub fn new(start: u32) -> Filter {
        Filter { id: start }
    }

    pub fn filter(&mut self, data: &impl IWithId) -> Result<(), Exception> {
        if data.get() > self.id || self.id - data.get() > MAX_ID_BREAK {
            self.id = data.get();
            Ok(())
        } else {
            Err(Exception::NotOrderedPacketError)
        }
    }
}

pub struct Arranger<T: IWithId> {
    last_valid_packet_id: u32,
    packets: HashMap<u32, T>,
    last_received_packet_id: u32,
    received: Vec<u32>,
}

const MAX_ID_BREAK: u32 = 32;
const MAX_SAVED: usize = (MAX_ID_BREAK * 4) as usize;
const MAX_RECEIVED: usize = MAX_SAVED;

impl<T: IWithId> Arranger<T> {
    pub fn new(last_id: u32) -> Arranger<T> {
        Arranger {
            last_valid_packet_id: last_id,
            packets: HashMap::new(),
            last_received_packet_id: 0,
            received: Vec::new(),
        }
    }

    pub fn arrange(&mut self) -> Vec<T> {
        let vec = self.get_valid();
        self.set_last_valid(&vec);
        vec
    }

    pub fn add(&mut self, data: T) -> Result<(), Exception> {
        let id = data.get();
        if id > self.last_received_packet_id + MAX_ID_BREAK {
            self.packets = HashMap::new();
            self.last_valid_packet_id = id - 1;
            self.received = Vec::new();
        }
        self.clear_if_overflows();
        if self.received.contains(&id) || data.get() + MAX_ID_BREAK < self.last_received_packet_id {
            Err(Exception::NotOrderedPacketError)
        } else {
            self.last_received_packet_id = id;
            self.packets.entry(id).or_insert(data);
            self.received.push(id);
            Ok(())
        }
    }

    fn clear_if_overflows(&mut self) {
        use itertools::*;

        if self.packets.len() > MAX_SAVED {
            let min_id = self
                .packets
                .iter()
                .min_by(|x, y| x.0.cmp(y.0))
                .map(|x| *x.0);
            min_id.map(|x| {
                self.last_valid_packet_id = if x > 0 { x - 1 } else { 0 };
            });
            self.packets = self
                .packets
                .drain()
                .sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
                .skip(MAX_SAVED / 2)
                .collect();
        }

        if self.received.len() > MAX_RECEIVED {
            self.received = self.received.clone().into_iter().skip(MAX_RECEIVED / 2).collect();
        }
    }

    fn set_last_valid(&mut self, packets: &[T]) {
        packets
            .iter()
            .map(|p| p.get())
            .max()
            .map(|max| self.last_valid_packet_id = max);
    }

    pub fn get_lost(&self) -> (u32, u32) {
        let mut sequence: u32 = 0;
        let mut x = 0;
        let mut y = self.last_received_packet_id;
        while x < 32 && y > 1 {
            y -= 1;
            if !self.received.contains(&y) {
                let mask = 1u32 << x;
                sequence |= mask;
            }
            x += 1;
        }
        (sequence, self.last_received_packet_id)
    }

    fn get_valid(&mut self) -> Vec<T> {
        let mut i = self.last_valid_packet_id + 1;
        let mut vec: Vec<T> = Vec::new();
        while self.packets.contains_key(&i) {
            vec.push(self.packets.remove(&i).unwrap());
            i += 1;
        }
        vec
    }
}