macro_rules! impl_nearest_segment {
($ffi_func:path) => {
pub fn nearest_segment<RD, SD, I>(&self, rect_dist: RD, seg_dist: SD, iter: I) -> bool
where
RD: FnMut(crate::Rect) -> (f64, bool),
SD: FnMut(crate::Segment) -> (f64, bool),
I: FnMut(crate::Segment, f64, usize) -> bool,
{
struct UserData<RD, SD, I> {
rect_dist: RD,
seg_dist: SD,
iter: I,
}
unsafe extern "C" fn rect_dist_trampoline<RD, SD, I>(
rect: tg_geom_sys::tg_rect, more: *mut libc::c_int, udata: *mut libc::c_void,
) -> f64
where
RD: FnMut(crate::Rect) -> (f64, bool),
SD: FnMut(crate::Segment) -> (f64, bool),
I: FnMut(crate::Segment, f64, usize) -> bool,
{
let ud = unsafe { &mut *(udata as *mut UserData<RD, SD, I>) };
let (dist, cont) = (ud.rect_dist)(rect.into());
unsafe {
*more = cont as libc::c_int;
}
dist
}
unsafe extern "C" fn seg_dist_trampoline<RD, SD, I>(
seg: tg_geom_sys::tg_segment, more: *mut libc::c_int, udata: *mut libc::c_void,
) -> f64
where
RD: FnMut(crate::Rect) -> (f64, bool),
SD: FnMut(crate::Segment) -> (f64, bool),
I: FnMut(crate::Segment, f64, usize) -> bool,
{
let ud = unsafe { &mut *(udata as *mut UserData<RD, SD, I>) };
let (dist, cont) = (ud.seg_dist)(seg.into());
unsafe {
*more = cont as libc::c_int;
}
dist
}
unsafe extern "C" fn iter_trampoline<RD, SD, I>(
seg: tg_geom_sys::tg_segment, dist: f64, index: libc::c_int,
udata: *mut libc::c_void,
) -> bool
where
RD: FnMut(crate::Rect) -> (f64, bool),
SD: FnMut(crate::Segment) -> (f64, bool),
I: FnMut(crate::Segment, f64, usize) -> bool,
{
let ud = unsafe { &mut *(udata as *mut UserData<RD, SD, I>) };
(ud.iter)(seg.into(), dist, index as usize)
}
let mut ud = UserData {
rect_dist,
seg_dist,
iter,
};
unsafe {
$ffi_func(
self.ptr.as_ptr(),
Some(rect_dist_trampoline::<RD, SD, I>),
Some(seg_dist_trampoline::<RD, SD, I>),
Some(iter_trampoline::<RD, SD, I>),
core::ptr::from_mut(&mut ud).cast(),
)
}
}
};
}
pub(crate) use impl_nearest_segment;