#![allow(dead_code)]
use std::alloc;
use std::mem;
use std::ptr;
use std::sync::Arc;
use crate::*;
pub(crate) struct ZerdeBuilder {
mu32: *mut u32,
mf32: *mut f32,
mu64: *mut u64,
mf64: *mut f64,
slots: usize,
used_slots: isize,
}
impl ZerdeBuilder {
pub(crate) fn new() -> Self {
unsafe {
let slots = 1024;
let buf =
alloc::alloc(alloc::Layout::from_size_align(4 * slots as usize, mem::align_of::<u32>()).unwrap()) as *mut u32;
(buf as *mut u64).write(4 * slots as u64);
Self {
mu32: buf as *mut u32,
mf32: buf as *mut f32,
mu64: buf as *mut u64,
mf64: buf as *mut f64,
slots,
used_slots: 2,
}
}
}
fn fit(&mut self, slots: usize) -> isize {
if self.used_slots as usize + slots > self.slots {
let mut new_slots = usize::max(self.used_slots as usize + slots, self.slots * 2);
if new_slots & 1 != 0 {
new_slots += 1;
}
let new_bytes = new_slots << 2;
let old_bytes = self.slots << 2;
let new_buf = unsafe {
let new_buf =
alloc::alloc(alloc::Layout::from_size_align(new_bytes as usize, mem::align_of::<u64>()).unwrap()) as *mut u32;
ptr::copy_nonoverlapping(self.mu32, new_buf, self.slots);
alloc::dealloc(
self.mu32 as *mut u8,
alloc::Layout::from_size_align(old_bytes as usize, mem::align_of::<u64>()).unwrap(),
);
(new_buf as *mut u64).write(new_bytes as u64);
new_buf
};
self.slots = new_slots;
self.mu32 = new_buf;
self.mf32 = new_buf as *mut f32;
self.mu64 = new_buf as *mut u64;
self.mf64 = new_buf as *mut f64;
}
let pos = self.used_slots;
self.used_slots += slots as isize;
pos
}
pub(crate) fn send_u32(&mut self, v: u32) {
let pos = self.fit(1);
unsafe {
self.mu32.offset(pos).write(v);
}
}
pub(crate) fn send_f32(&mut self, v: f32) {
let pos = self.fit(1);
unsafe {
self.mf32.offset(pos).write(v);
}
}
pub(crate) fn send_f64(&mut self, v: f64) {
if self.used_slots & 1 != 0 {
self.fit(1);
}
let pos = self.fit(2);
unsafe {
self.mf64.offset(pos >> 1).write(v);
}
}
pub(crate) fn send_u64(&mut self, v: u64) {
if self.used_slots & 1 != 0 {
self.fit(1);
}
let pos = self.fit(2);
unsafe {
self.mu64.offset(pos >> 1).write(v);
}
}
pub(crate) fn send_string(&mut self, msg: &str) {
let len = msg.chars().count();
self.send_u32(len as u32);
for c in msg.chars() {
self.send_u32(c as u32);
}
}
pub(crate) fn send_u8slice(&mut self, msg: &[u8]) {
let u8_len = msg.len();
let len = u8_len >> 2;
let spare = u8_len & 3;
self.send_u32(u8_len as u32);
for i in 0..len {
self.send_u32(
(msg[(i << 2)] as u32)
| ((msg[(i << 2) + 1] as u32) << 8)
| ((msg[(i << 2) + 2] as u32) << 16)
| ((msg[(i << 2) + 3] as u32) << 24),
);
}
match spare {
1 => self.send_u32(msg[(len << 2)] as u32),
2 => self.send_u32((msg[(len << 2)] as u32) | ((msg[(len << 2) + 1] as u32) << 8)),
3 => self
.send_u32((msg[(len << 2)] as u32) | ((msg[(len << 2) + 1] as u32) << 8) | ((msg[(len << 2) + 2] as u32) << 16)),
_ => (),
}
}
fn build_mutable_buffer<T>(&mut self, buffer_type: u32, mut buffer: Vec<T>) {
self.send_u32(buffer_type);
self.send_u32(buffer.as_mut_ptr() as u32);
self.send_u32((buffer.len() * std::mem::size_of::<T>()) as u32);
self.send_u32((buffer.capacity() * std::mem::size_of::<T>()) as u32);
mem::forget(buffer);
}
fn build_read_only_buffer<T>(&mut self, buffer_type: u32, buffer: Arc<Vec<T>>) {
self.send_u32(buffer_type);
self.send_u32(buffer.as_ptr() as u32);
self.send_u32((buffer.len() * std::mem::size_of::<T>()) as u32);
let arc_ptr = Arc::into_raw(Arc::clone(&buffer)) as u32;
self.send_u32(arc_ptr);
}
pub(crate) fn build_zap_params(&mut self, params: Vec<ZapParam>) {
self.send_u32(params.len() as u32);
for param in params {
match param {
ZapParam::String(str) => {
self.send_u32(ZAP_PARAM_STRING);
self.send_string(&str);
}
ZapParam::ReadOnlyU8Buffer(buffer) => {
self.build_read_only_buffer(ZAP_PARAM_READ_ONLY_UINT8_BUFFER, buffer);
}
ZapParam::MutableU8Buffer(buffer) => {
self.build_mutable_buffer(ZAP_PARAM_UINT8_BUFFER, buffer);
}
ZapParam::ReadOnlyF32Buffer(buffer) => {
self.build_read_only_buffer(ZAP_PARAM_READ_ONLY_FLOAT32_BUFFER, buffer);
}
ZapParam::MutableF32Buffer(buffer) => {
self.build_mutable_buffer(ZAP_PARAM_FLOAT32_BUFFER, buffer);
}
}
}
}
pub(crate) fn take_ptr(self ) -> u64 {
self.mu32 as u64
}
}
pub(crate) struct ZerdeParser {
mu32: *mut u32,
mf32: *mut f32,
mu64: *mut u64,
mf64: *mut f64,
slots: usize,
used_slots: isize,
}
impl Drop for ZerdeParser {
fn drop(&mut self) {
unsafe {
alloc::dealloc(
self.mu32 as *mut u8,
alloc::Layout::from_size_align((self.slots * mem::size_of::<u64>()) as usize, mem::align_of::<u32>()).unwrap(),
);
}
}
}
impl ZerdeParser {
pub(crate) fn from(buf: u64) -> ZerdeParser {
unsafe {
let bytes = (buf as *mut u64).read() as usize;
ZerdeParser {
mu32: buf as *mut u32,
mf32: buf as *mut f32,
mu64: buf as *mut u64,
mf64: buf as *mut f64,
used_slots: 2,
slots: bytes >> 2,
}
}
}
pub(crate) fn parse_u32(&mut self) -> u32 {
unsafe {
let ret = self.mu32.offset(self.used_slots).read();
self.used_slots += 1;
ret
}
}
pub(crate) fn parse_f32(&mut self) -> f32 {
unsafe {
let ret = self.mf32.offset(self.used_slots).read();
self.used_slots += 1;
ret
}
}
pub(crate) fn parse_f64(&mut self) -> f64 {
unsafe {
if self.used_slots & 1 != 0 {
self.used_slots += 1;
}
let ret = self.mf64.offset(self.used_slots >> 1).read();
self.used_slots += 2;
ret
}
}
pub(crate) fn parse_u64(&mut self) -> u64 {
unsafe {
if self.used_slots & 1 != 0 {
self.used_slots += 1;
}
let ret = self.mu64.offset(self.used_slots >> 1).read();
self.used_slots += 2;
ret
}
}
pub(crate) fn parse_string(&mut self) -> String {
let len = self.parse_u32();
let mut out = String::with_capacity(len as usize);
for _ in 0..len {
if let Some(c) = std::char::from_u32(self.parse_u32()) {
out.push(c);
}
}
out
}
pub(crate) fn parse_vec_ptr(&mut self) -> Vec<u8> {
let vec_ptr = self.parse_u32() as *mut u8;
let vec_len = self.parse_u32() as usize;
unsafe { Vec::<u8>::from_raw_parts(vec_ptr, vec_len, vec_len) }
}
pub(crate) fn parse_arc_vec<T>(&mut self) -> Arc<Vec<T>> {
let arc_ptr = self.parse_u32() as *const Vec<T>;
unsafe { Arc::from_raw(arc_ptr) }
}
fn parse_buffer<T>(&mut self) -> Vec<T> {
let vec_ptr = self.parse_u32();
let vec_len = self.parse_u32() as usize / std::mem::size_of::<T>();
let vec_cap = self.parse_u32() as usize / std::mem::size_of::<T>();
unsafe { Vec::from_raw_parts(vec_ptr as *mut T, vec_len, vec_cap) }
}
pub(crate) fn parse_zap_params(&mut self) -> Vec<ZapParam> {
let len = self.parse_u32();
(0..len)
.map(|_| {
let param_type = self.parse_u32();
match param_type {
ZAP_PARAM_STRING => self.parse_string().into_param(),
ZAP_PARAM_READ_ONLY_UINT8_BUFFER => self.parse_arc_vec::<u8>().into_param(),
ZAP_PARAM_READ_ONLY_FLOAT32_BUFFER => self.parse_arc_vec::<f32>().into_param(),
ZAP_PARAM_UINT8_BUFFER => self.parse_buffer::<u8>().into_param(),
ZAP_PARAM_FLOAT32_BUFFER => self.parse_buffer::<f32>().into_param(),
value => panic!("Unexpected param type: {}", value),
}
})
.collect()
}
}