use cyberex::void::HyVoidConst;
use crate::sys::*;
use std::{ffi::c_void, ops::Deref};
pub trait ICVecImpl<T> {
fn fn_free(ctx: *const c_void);
fn fn_data(ctx: *const c_void) -> *const T;
fn fn_size(ctx: *const c_void) -> usize;
}
impl ICVecImpl<u8> for u8 {
fn fn_free(ctx: *const c_void) {
unsafe { codec_vec_uint8_free(ctx) }
}
fn fn_data(ctx: *const c_void) -> *const u8 {
unsafe { codec_vec_uint8_data(ctx) }
}
fn fn_size(ctx: *const c_void) -> usize {
unsafe { codec_vec_uint8_size(ctx) }
}
}
pub struct CVecView<T>
where
T: ICVecImpl<T>,
{
ctx: HyVoidConst<()>,
_mark: std::marker::PhantomData<T>,
}
impl<T> CVecView<T>
where
T: ICVecImpl<T>,
{
pub fn new(ptr: *const c_void) -> Self {
let ctx = HyVoidConst::from_ptr(ptr);
Self {
ctx,
_mark: std::marker::PhantomData,
}
}
fn len(&self) -> usize {
let ctx = self.ctx.as_ptr();
T::fn_size(ctx)
}
fn ptr(&self) -> *const T {
let ctx = self.ctx.as_ptr();
T::fn_data(ctx).cast()
}
fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn as_slice(&self) -> &[T] {
if self.is_empty() {
return &[];
}
unsafe { std::slice::from_raw_parts(self.ptr(), self.len()) }
}
}
impl<T> From<*const c_void> for CVecView<T>
where
T: ICVecImpl<T>,
{
fn from(ptr: *const c_void) -> Self {
CVecView::new(ptr)
}
}
impl<T> Deref for CVecView<T>
where
T: ICVecImpl<T>,
{
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T> Drop for CVecView<T>
where
T: ICVecImpl<T>,
{
fn drop(&mut self) {
let ptr = self.ctx.as_ptr();
T::fn_free(ptr);
}
}