#![cfg(any(feature = "picodata", doc))]
use libc::{iovec, size_t};
use std::cmp;
use std::io::Read;
use std::os::raw::{c_char, c_int, c_void};
pub const IPROTO_DATA: u8 = 0x30;
crate::define_dlsym_reloc! {
pub(crate) fn cord_slab_cache() -> *const SlabCache;
pub(crate) fn obuf_create(obuf: *mut Obuf, slab_cache: *const SlabCache, start_cap: size_t);
pub(crate) fn obuf_destroy(obuf: *mut Obuf);
pub fn ibuf_reinit(ibuf: *mut Ibuf);
pub(crate) fn sql_prepare_ext(sql: *const u8, len: u32, stmt_id: *mut u32) -> c_int;
pub(crate) fn sql_execute_prepared_ext(
stmt_id: u32,
mp_params: *const u8,
vdbe_max_steps: u64,
obuf: *mut Obuf,
) -> c_int;
pub(crate) fn sql_unprepare(stmt_id: u32) -> c_int;
pub(crate) fn sql_stmt_calculate_id(sql_str: *const c_char, len: size_t) -> u32;
pub(crate) fn sql_prepare_and_execute_ext(
sql: *const u8,
len: c_int,
mp_params: *const u8,
vdbe_max_steps: u64,
obuf: *mut Obuf,
) -> c_int;
}
#[repr(C)]
pub(crate) struct SlabCache {
_unused: [u8; 0],
}
#[repr(C)]
pub struct Ibuf {
_slab_cache: *mut SlabCache,
pub buf: *mut u8,
pub rpos: *mut u8,
pub wpos: *mut u8,
pub epos: *mut u8,
start_capacity: usize,
}
pub(crate) struct ObufWrapper {
pub inner: Obuf,
read_pos: usize,
read_iov_n: usize,
read_iov_pos: usize,
}
impl ObufWrapper {
pub fn new(start_capacity: usize) -> Self {
let inner_buf = unsafe {
let slab_c = cord_slab_cache();
let mut buf = Obuf {
_slab_cache: std::mem::zeroed(),
pos: 0,
n_iov: 0,
used: 0,
start_capacity: start_capacity as size_t,
capacity: std::mem::zeroed(),
iov: std::mem::zeroed(),
};
obuf_create(&mut buf as *mut Obuf, slab_c, 1024);
buf
};
Self {
inner: inner_buf,
read_pos: 0,
read_iov_n: 0,
read_iov_pos: 0,
}
}
pub(crate) fn obuf(&mut self) -> *mut Obuf {
&mut self.inner as *mut Obuf
}
}
impl Read for ObufWrapper {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut remains_read = cmp::min(buf.len(), self.inner.used - self.read_pos);
let mut buf_pos = 0;
while remains_read > 0 {
let iov_available_len = self.inner.iov[self.read_iov_n].iov_len - self.read_iov_pos;
if iov_available_len == 0 {
self.read_iov_n += 1;
self.read_iov_pos = 0;
continue;
}
let read_len = if iov_available_len <= remains_read {
iov_available_len
} else {
remains_read
};
let cp = unsafe {
std::slice::from_raw_parts(
(self.inner.iov[self.read_iov_n].iov_base as *const u8).add(self.read_iov_pos),
read_len,
)
};
buf[buf_pos..buf_pos + read_len].copy_from_slice(cp);
buf_pos += read_len;
remains_read -= read_len;
self.read_iov_pos += read_len;
}
self.read_pos += buf_pos;
Ok(buf_pos)
}
}
#[repr(C)]
pub(crate) struct Obuf {
_slab_cache: *const c_void,
pub pos: i32,
pub n_iov: i32,
pub used: size_t,
pub start_capacity: size_t,
pub capacity: [size_t; 32],
pub iov: [iovec; 32],
}
impl Drop for Obuf {
fn drop(&mut self) {
unsafe { obuf_destroy(self as *mut Obuf) }
}
}