use std::ffi::c_void;
use std::ptr;
use crate::ffi::{vmod_data, vmod_priv, vmod_priv_methods, vrt_ctx};
use crate::validate_vrt_ctx;
use crate::vcl::PerVclState;
unsafe impl Sync for vmod_data {}
unsafe fn get_owned_bbox<T>(priv_: &mut *mut c_void) -> Option<Box<T>> {
let obj = ptr::replace(priv_, ptr::null_mut());
if obj.is_null() {
None
} else {
Some(Box::from_raw(obj.cast::<T>()))
}
}
impl vmod_priv {
pub unsafe fn take<T>(&mut self) -> Option<Box<T>> {
self.methods = ptr::null();
get_owned_bbox(&mut self.priv_)
}
#[expect(clippy::unnecessary_box_returns)]
pub unsafe fn take_per_vcl<T>(&mut self) -> Box<PerVclState<T>> {
if let Some(v) = self.take::<PerVclState<T>>() {
v
} else {
let o = PerVclState::<T>::default();
Box::new(o)
}
}
pub unsafe fn get_ref<T>(&self) -> Option<&T> {
self.priv_.cast::<T>().as_ref()
}
}
unsafe impl Sync for vmod_priv_methods {}
impl vmod_priv {
pub unsafe fn put<T>(&mut self, obj: Box<T>, methods: &'static vmod_priv_methods) {
self.priv_ = Box::into_raw(obj).cast();
self.methods = methods;
}
pub unsafe extern "C" fn on_fini<T>(_ctx: *const vrt_ctx, mut priv_: *mut c_void) {
drop(get_owned_bbox::<T>(&mut priv_));
}
pub unsafe extern "C" fn on_fini_per_vcl<T>(ctx: *const vrt_ctx, mut priv_: *mut c_void) {
if let Some(obj) = get_owned_bbox::<PerVclState<T>>(&mut priv_) {
let PerVclState {
mut fetch_filters,
mut delivery_filters,
user_data,
} = *obj;
let ctx = validate_vrt_ctx(ctx);
ctx.fetch_filters(&mut fetch_filters).unregister_all();
ctx.delivery_filters(&mut delivery_filters).unregister_all();
drop(user_data);
}
}
}