Repository: launchbadge/sqlx
File: sqlx-core/src/sqlite/connection/collation.rs (Rust)

Code before:
    unsafe extern "C" fn call_boxed_closure<C>(
        arg1: *mut c_void,
        arg2: c_int,
        arg3: *const c_void,
        arg4: c_int,
        arg5: *const c_void,
    ) -> c_int
    where
        C: Fn(&str, &str) -> Ordering,
    {
        let r = catch_unwind(|| {
            let boxed_f: *mut C = arg1 as *mut C;
            assert!(!boxed_f.is_null(), "Internal error - null function pointer");
            let s1 = {
                let c_slice = slice::from_raw_parts(arg3 as *const u8, arg2 as usize);
                String::from_utf8_lossy(c_slice)
            };
            let s2 = {
                let c_slice = slice::from_raw_parts(arg5 as *const u8, arg4 as usize);
                String::from_utf8_lossy(c_slice)
            };
            (*boxed_f)(s1.as_ref(), s2.as_ref())
        });
        let t = match r {
            Err(_) => {
                return -1; // FIXME How ?
            }
            Ok(r) => r,
        };

        match t {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1,
        }
    }

    let boxed_f: *mut F = Box::into_raw(Box::new(collation));
    let c_name =
        CString::new(name).map_err(|_| err_protocol!("Invalid collation name: {}", name))?;
    let flags = SQLITE_UTF8;
    let r = unsafe {
        sqlite3_create_collation_v2(
            handle.as_ptr(),
            c_name.as_ptr(),
            flags,
            boxed_f as *mut c_void,
            Some(call_boxed_closure::<F>),
            Some(free_boxed_value::<F>),
        )
    };

Review comment (suggestion):
If I understand https://github.com/rust-lang/rust/pull/55982 correctly, you can remove the unwind stuff completely. If a panic happens in the boxed function, Rust should immediately abort, which is the correct behavior in this case.

cc @gwenn as this code is from rusqlite

Code after:
    unsafe extern "C" fn call_boxed_closure<C>(
        arg1: *mut c_void,
        arg2: c_int,
        arg3: *const c_void,
        arg4: c_int,
        arg5: *const c_void,
    ) -> c_int
    where
        C: Fn(&str, &str) -> Ordering,
    {
        let boxed_f: *mut C = arg1 as *mut C;
        debug_assert!(!boxed_f.is_null());
        let s1 = {
            let c_slice = slice::from_raw_parts(arg3 as *const u8, arg2 as usize);
            from_utf8_unchecked(c_slice)
        };
        let s2 = {
            let c_slice = slice::from_raw_parts(arg5 as *const u8, arg4 as usize);
            from_utf8_unchecked(c_slice)
        };
        let t = (*boxed_f)(s1, s2);

        match t {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1,
        }
    }

    let boxed_f: *mut F = Box::into_raw(Box::new(compare));
    let c_name =
        CString::new(name).map_err(|_| err_protocol!("invalid collation name: {}", name))?;
    let flags = SQLITE_UTF8;
    let r = unsafe {
        sqlite3_create_collation_v2(
            handle.as_ptr(),
            c_name.as_ptr(),
            flags,
            boxed_f as *mut c_void,
            Some(call_boxed_closure::<F>),
            Some(free_boxed_value::<F>),
        )
    };

    if r == SQLITE_OK {
        Ok(())
    } else {
        Err(Error::Database(Box::new(SqliteError::new(handle.as_ptr()))))
    }
}