use std::ffi::c_char;
use geopackage::Finding;
use crate::error::{Status, gpkg_error_t, set_error, set_library_error};
use crate::handle::Container;
use crate::util::write_out_strings;
pub struct FindingsHandle {
findings: Vec<Finding>,
}
#[expect(
non_camel_case_types,
reason = "the C name is the type's name; cbindgen emits it verbatim"
)]
pub type gpkg_findings_t = FindingsHandle;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn gpkg_validate(
gpkg: *const Container,
out: *mut *mut gpkg_findings_t,
error: *mut gpkg_error_t,
) -> Status {
if gpkg.is_null() || out.is_null() {
unsafe { set_error(error, Status::BadArgument, "gpkg handle or out is NULL") };
return Status::BadArgument;
}
match unsafe { (*gpkg).gpkg().validate() } {
Ok(findings) => {
let handle = Box::new(FindingsHandle { findings });
unsafe { *out = Box::into_raw(handle) };
Status::Ok
}
Err(err) => {
unsafe { set_library_error(error, &err) };
Status::from(&err)
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn gpkg_findings_free(findings: *mut gpkg_findings_t) {
if findings.is_null() {
return;
}
drop(unsafe { Box::from_raw(findings) });
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn gpkg_findings_count(findings: *const gpkg_findings_t) -> usize {
if findings.is_null() {
return 0;
}
let handle = unsafe { &*findings };
handle.findings.len()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn gpkg_finding_at(
findings: *const gpkg_findings_t,
index: usize,
out_severity: *mut *mut c_char,
out_message: *mut *mut c_char,
out_repair: *mut *mut c_char,
error: *mut gpkg_error_t,
) -> Status {
if findings.is_null() {
unsafe { set_error(error, Status::BadArgument, "findings handle is NULL") };
return Status::BadArgument;
}
let handle = unsafe { &*findings };
let Some(finding) = handle.findings.get(index) else {
unsafe { set_error(error, Status::NotFound, "finding index out of range") };
return Status::NotFound;
};
let slots = [
(out_severity, Some(finding.severity().to_string())),
(out_message, Some(finding.to_string())),
(out_repair, finding.repair().map(str::to_owned)),
];
if unsafe { write_out_strings(&slots, error) } {
Status::Ok
} else {
Status::InvalidArgument
}
}