tg-geom 0.0.0

Rust bindings for the `TG` Geometry library.
Documentation
//! Internal utilities.

macro_rules! impl_nearest_segment {
    ($ffi_func:path) => {
        /// Iterates segments by distance. Returns `true` if completed.
        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;