reqrio 0.3.0-alpha2

A lightweight, high-performance, fingerprint-based HTTP request library.
Documentation
use std::ptr;
use crate::error::HlsResult;
use crate::HlsError;
use crate::packet::ws::Marker;

pub struct WsPayload {
    len: usize,
    mask: [u8; 4],
    payload: Vec<u8>,
}

impl WsPayload {
    pub fn new() -> WsPayload {
        WsPayload {
            len: 0,
            mask: [43, 34, 56, 23],
            payload: vec![],
        }
    }

    pub(crate) fn copy_payload(&mut self, payload: &[u8], masker: &Marker) {
        self.payload.reserve(payload.len());
        let dst = self.payload.as_mut_ptr();
        unsafe { ptr::copy_nonoverlapping(payload.as_ptr(), dst, payload.len()) };
        unsafe { self.payload.set_len(payload.len()); }
        if masker.mask {
            self.payload.iter_mut().enumerate().for_each(|(i, b)| *b ^= self.mask[i % 4])
        }
        self.len = payload.len();
    }

    pub fn from_bytes(masker: &Marker, bytes: &[u8]) -> HlsResult<WsPayload> {
        let mut res = WsPayload::new();
        match masker.len_code {
            127 => {
                if bytes.len() < 8 { return Err(HlsError::DataTooShort); }
                res.len = u64::from_be_bytes(bytes[..8].try_into()?) as usize;
                if masker.mask {
                    if bytes.len() < res.len + 4 + 8 { return Err(HlsError::DataTooShort); }
                    res.mask.copy_from_slice(&bytes[8..12]);
                    res.copy_payload(&bytes[12..12 + res.len], masker);
                } else {
                    if bytes.len() < res.len + 8 { return Err(HlsError::DataTooShort); }
                    res.copy_payload(&bytes[8..8 + res.len], masker);
                }
            }
            126 => {
                res.len = u16::from_be_bytes(bytes[..2].try_into()?) as usize;
                if masker.mask {
                    if bytes.len() < res.len + 4 + 2 { return Err(HlsError::DataTooShort); }
                    res.mask.copy_from_slice(&bytes[2..6]);
                    res.copy_payload(&bytes[6..6 + res.len], masker);
                } else {
                    if bytes.len() < res.len + 2 { return Err(HlsError::DataTooShort); }
                    res.copy_payload(&bytes[2..2 + res.len], masker);
                }
            }
            _ => {
                res.len = masker.len_code as usize;
                if masker.mask {
                    if bytes.len() < res.len + 4 { return Err(HlsError::DataTooShort); }
                    res.mask.copy_from_slice(&bytes[..4]);
                    res.copy_payload(&bytes[4..4 + res.len], masker);
                } else {
                    if bytes.len() < res.len { return Err(HlsError::DataTooShort); }
                    res.copy_payload(&bytes[..res.len], masker);
                }
            }
        }
        Ok(res)
    }

    pub fn as_bytes(&self) -> &[u8] {
        &self.payload
    }

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

    pub fn to_bytes(self, masker: &Marker) -> Vec<u8> {
        let mut res = if masker.mask { self.mask.to_vec() } else { vec![] };
        res.extend(self.payload);
        res
    }
}