use std::{cmp::max, mem::size_of, ptr::null};
use smallvec::SmallVec;
use crate::ArgSlice;
pub const INLINE_PARAMS: usize = 8;
#[derive(Debug, Clone)]
pub struct SessionParseState {
pub count: usize,
pub root_buffer: SmallVec<[ArgSlice; INLINE_PARAMS]>,
pub offset: usize,
}
impl Default for SessionParseState {
fn default() -> Self {
Self::new()
}
}
impl SessionParseState {
pub const MIN_PARAMS: usize = 5;
#[inline]
pub fn new() -> Self {
Self {
count: 0,
root_buffer: SmallVec::new(),
offset: 0,
}
}
#[inline]
pub fn initialize(&mut self, count: usize) {
self.count = count;
self.offset = 0;
let cap = max(count, Self::MIN_PARAMS);
self.root_buffer.clear();
self.root_buffer.resize(cap, ArgSlice::new(null(), 0));
}
#[inline]
pub fn initialize_with_arg(&mut self, arg: ArgSlice) {
self.initialize(1);
self.root_buffer[0] = arg;
}
#[inline]
pub fn initialize_with_args(&mut self, args: &[ArgSlice]) {
self.initialize(args.len());
for (i, &arg) in args.iter().enumerate() {
self.root_buffer[i] = arg;
}
}
#[inline]
pub fn slice(&self, idx_offset: usize) -> Self {
let new_count = self.count.saturating_sub(idx_offset);
let start = self.offset + idx_offset;
let end = (start + new_count).min(self.root_buffer.len());
let mut root_buffer = SmallVec::new();
if start < end {
root_buffer.extend_from_slice(&self.root_buffer[start..end]);
}
Self {
count: new_count,
root_buffer,
offset: 0,
}
}
#[inline]
pub fn get_arg_slice_by_ref(&self, i: usize) -> ArgSlice {
debug_assert!(i < self.count);
self.root_buffer[self.offset + i]
}
pub fn get_serialized_length(&self) -> usize {
let mut len = size_of::<i32>();
for arg in &self.root_buffer[self.offset..self.offset + self.count] {
len += arg.total_size();
}
len
}
pub unsafe fn serialize_to(&self, dest: *mut u8, length: usize) -> usize {
unsafe {
let mut curr = dest;
(curr as *mut i32).write_unaligned(self.count as i32);
curr = curr.add(size_of::<i32>());
for arg in &self.root_buffer[self.offset..self.offset + self.count] {
arg.serialize_to(curr);
curr = curr.add(arg.total_size());
}
let written = (curr as usize) - (dest as usize);
debug_assert!(written <= length, "写入字节数超出预留容量上限");
written
}
}
pub unsafe fn deserialize_from(&mut self, src: *const u8) -> usize {
unsafe {
let mut curr = src;
let raw_count = (curr as *const i32).read_unaligned();
if raw_count < 0 {
return 0;
}
let arg_count = raw_count as usize;
curr = curr.add(size_of::<i32>());
self.initialize(arg_count);
for slot in self.root_buffer.iter_mut().take(arg_count) {
let arg = ArgSlice::from_length_prefixed_ptr(curr);
curr = curr.add(arg.total_size());
*slot = arg;
}
(curr as usize) - (src as usize)
}
}
}