#![allow(non_camel_case_types)]
use std::marker::{PhantomData, PhantomPinned};
use std::os::raw::{c_char, c_int};
pub const SEMQ_FILE_VERSION: u32 = 2;
pub const SEMQ_RULE_REVISION: u32 = 0;
pub const SEMQ_CONFIG_BYTES: u32 = 13;
pub const SEMQ_DIGEST_BYTES: u32 = 32;
pub const SEMQ_MAX_DIM: u32 = 65536;
pub const SEMQ_ID_MAX_BYTES: u32 = 4096;
pub const SEMQ_MANIFEST_MAX_PAIRS: u32 = 4096;
pub const SEMQ_MANIFEST_KEY_MAX: u32 = 256;
pub const SEMQ_MANIFEST_VALUE_MAX: u32 = 65536;
pub const SEMQ_MANIFEST_SECTION_MAX: u32 = 16 * 1024 * 1024;
pub const SEMQ_NONE: u64 = u64::MAX;
pub type semq_operator_t = u32;
pub const SEMQ_ORBIT: semq_operator_t = 0;
pub const SEMQ_PHASE: semq_operator_t = 1;
pub const SEMQ_QUANT: semq_operator_t = 2;
pub type semq_id_kind_t = u32;
pub const SEMQ_ID_U64: semq_id_kind_t = 0;
pub const SEMQ_ID_UTF8: semq_id_kind_t = 1;
pub type semq_status_t = u32;
pub const SEMQ_OK: semq_status_t = 0;
pub const SEMQ_ERR_INVALID_INPUT: semq_status_t = 1;
pub const SEMQ_ERR_INCOMPATIBLE: semq_status_t = 2;
pub const SEMQ_ERR_FORMAT: semq_status_t = 3;
pub const SEMQ_ERR_INTEGRITY: semq_status_t = 4;
pub const SEMQ_ERR_UNSUPPORTED: semq_status_t = 5;
pub const SEMQ_ERR_NOMEM: semq_status_t = 6;
pub const SEMQ_ERR_INTERNAL: semq_status_t = 7;
pub type semq_which_t = u32;
pub const SEMQ_WHICH_NONE: semq_which_t = 0;
pub const SEMQ_WHICH_CONTENT: semq_which_t = 1;
pub const SEMQ_WHICH_STATE: semq_which_t = 2;
pub type semq_section_t = u32;
pub const SEMQ_SECTION_FRAMING: semq_section_t = 0;
pub const SEMQ_SECTION_CONFIG: semq_section_t = 1;
pub const SEMQ_SECTION_SIZES: semq_section_t = 2;
pub const SEMQ_SECTION_IDS: semq_section_t = 3;
pub const SEMQ_SECTION_MANIFEST: semq_section_t = 4;
pub const SEMQ_SECTION_FOOTER: semq_section_t = 5;
pub const SEMQ_SECTION_ROWS: semq_section_t = 6;
pub type semq_config_field_t = u32;
pub const SEMQ_FIELD_OPERATOR: semq_config_field_t = 0;
pub const SEMQ_FIELD_DIM: semq_config_field_t = 1;
pub const SEMQ_FIELD_P1: semq_config_field_t = 2;
pub const SEMQ_FIELD_P2: semq_config_field_t = 3;
pub type semq_list_t = u32;
pub const SEMQ_LIST_ADDED: semq_list_t = 0;
pub const SEMQ_LIST_REMOVED: semq_list_t = 1;
pub const SEMQ_LIST_CHANGED: semq_list_t = 2;
pub type semq_check_t = u32;
pub const SEMQ_CHECK_PER_ROW: semq_check_t = 1;
pub type semq_reason_t = u32;
pub const SEMQ_REASON_NO_COMMON_ROWS: semq_reason_t = 1;
pub const SEMQ_REASON_REMOVED_ROWS: semq_reason_t = 2;
pub const SEMQ_REASON_CHANGED_RATIO: semq_reason_t = 4;
pub const SEMQ_REASON_HAMMING: semq_reason_t = 8;
pub const SEMQ_REASON_ENCODER: semq_reason_t = 16;
pub const SEMQ_REASON_ROW_ABOVE_MAX: semq_reason_t = 32;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct semq_error_t {
pub status: u32,
pub which: u32,
pub row: u64,
pub field: u64,
pub message: [c_char; 128],
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct semq_config_t {
pub op: u32,
pub dim: u32,
pub p1: u32,
pub p2: u32,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct semq_pair_t {
pub key: *const u8,
pub key_len: u32,
pub value: *const u8,
pub value_len: u32,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct semq_ids_t {
pub kind: u32,
pub n: u64,
pub u64: *const u64,
pub utf8_offsets: *const u64,
pub utf8_bytes: *const u8,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct semq_part_t {
pub ptr: *const u8,
pub len: u64,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct semq_manifest_change_t {
pub key: *const u8,
pub key_len: u32,
pub has_before: c_int,
pub before: *const u8,
pub before_len: u32,
pub has_after: c_int,
pub after: *const u8,
pub after_len: u32,
}
#[repr(C)]
pub struct semq_codec_t {
_data: [u8; 0],
_marker: PhantomData<(*mut u8, PhantomPinned)>,
}
#[repr(C)]
pub struct semq_encoding_t {
_data: [u8; 0],
_marker: PhantomData<(*mut u8, PhantomPinned)>,
}
#[repr(C)]
pub struct semq_diff_t {
_data: [u8; 0],
_marker: PhantomData<(*mut u8, PhantomPinned)>,
}
#[repr(C)]
pub struct semq_floor_t {
_data: [u8; 0],
_marker: PhantomData<(*mut u8, PhantomPinned)>,
}
#[repr(C)]
pub struct semq_verdict_t {
_data: [u8; 0],
_marker: PhantomData<(*mut u8, PhantomPinned)>,
}
extern "C" {
pub fn semq_config_orbit(
dim: u32,
scale: u32,
out: *mut semq_config_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_config_phase(
dim: u32,
sectors: u32,
out: *mut semq_config_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_config_quant(
dim: u32,
bins: u32,
out: *mut semq_config_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_config_validate(cfg: *const semq_config_t, err: *mut semq_error_t)
-> semq_status_t;
pub fn semq_config_to_bytes(cfg: *const semq_config_t, out: *mut u8);
pub fn semq_config_from_bytes(
input: *const u8,
out: *mut semq_config_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_config_bytes_per_vector(cfg: *const semq_config_t) -> u32;
pub fn semq_config_units_per_row(cfg: *const semq_config_t) -> u32;
pub fn semq_config_max_magnitude(cfg: *const semq_config_t) -> f32;
pub fn semq_config_equal(a: *const semq_config_t, b: *const semq_config_t) -> c_int;
pub fn semq_codec_create(
cfg: *const semq_config_t,
out: *mut *mut semq_codec_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_codec_free(codec: *mut semq_codec_t);
pub fn semq_codec_config(codec: *const semq_codec_t) -> *const semq_config_t;
pub fn semq_codec_backend(codec: *const semq_codec_t) -> *const c_char;
pub fn semq_codec_encode(
codec: *const semq_codec_t,
ids: *const semq_ids_t,
vectors: *const f32,
manifest: *const semq_pair_t,
n_pairs: u32,
out: *mut *mut semq_encoding_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_codec_decode(
codec: *const semq_codec_t,
enc: *const semq_encoding_t,
out: *mut f32,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_codec_unpack(
codec: *const semq_codec_t,
enc: *const semq_encoding_t,
out: *mut u8,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_create(
cfg: *const semq_config_t,
ids: *const semq_ids_t,
rows: *const u8,
manifest: *const semq_pair_t,
n_pairs: u32,
out: *mut *mut semq_encoding_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_free(enc: *mut semq_encoding_t);
pub fn semq_encoding_config(enc: *const semq_encoding_t) -> *const semq_config_t;
pub fn semq_encoding_id_kind(enc: *const semq_encoding_t) -> u32;
pub fn semq_encoding_len(enc: *const semq_encoding_t) -> u64;
pub fn semq_encoding_rows(enc: *const semq_encoding_t, len: *mut u64) -> *const u8;
pub fn semq_encoding_ids_u64(enc: *const semq_encoding_t) -> *const u64;
pub fn semq_encoding_ids_utf8_offsets(enc: *const semq_encoding_t) -> *const u64;
pub fn semq_encoding_ids_utf8_bytes(enc: *const semq_encoding_t, len: *mut u64) -> *const u8;
pub fn semq_encoding_manifest_len(enc: *const semq_encoding_t) -> u32;
pub fn semq_encoding_manifest_pair(
enc: *const semq_encoding_t,
i: u32,
out: *mut semq_pair_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_content_digest(enc: *const semq_encoding_t, out: *mut u8);
pub fn semq_encoding_state_id(enc: *const semq_encoding_t, out: *mut u8);
pub fn semq_encoding_find_u64(
enc: *const semq_encoding_t,
id: u64,
index: *mut u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_find_utf8(
enc: *const semq_encoding_t,
id: *const u8,
len: u64,
index: *mut u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_file_size(enc: *const semq_encoding_t) -> u64;
pub fn semq_encoding_save_parts(enc: *const semq_encoding_t, parts: *mut semq_part_t) -> u32;
pub fn semq_encoding_save(
enc: *const semq_encoding_t,
out: *mut u8,
cap: u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_load(
buf: *const u8,
len: u64,
out: *mut *mut semq_encoding_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_concat(
parts: *const *const semq_encoding_t,
k: u32,
out: *mut *mut semq_encoding_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_encoding_diff(
reference: *const semq_encoding_t,
candidate: *const semq_encoding_t,
out: *mut *mut semq_diff_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_diff_free(diff: *mut semq_diff_t);
pub fn semq_diff_config(diff: *const semq_diff_t) -> *const semq_config_t;
pub fn semq_diff_id_kind(diff: *const semq_diff_t) -> u32;
pub fn semq_diff_reference_id(diff: *const semq_diff_t, out: *mut u8);
pub fn semq_diff_candidate_id(diff: *const semq_diff_t, out: *mut u8);
pub fn semq_diff_count(diff: *const semq_diff_t, list: u32) -> u64;
pub fn semq_diff_n_unchanged(diff: *const semq_diff_t) -> u64;
pub fn semq_diff_id(
diff: *const semq_diff_t,
list: u32,
i: u64,
out_u64: *mut u64,
bytes: *mut *const u8,
len: *mut u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_diff_hamming(
diff: *const semq_diff_t,
i: u64,
out: *mut u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_diff_manifest_changes(diff: *const semq_diff_t) -> u32;
pub fn semq_diff_manifest_change(
diff: *const semq_diff_t,
i: u32,
out: *mut semq_manifest_change_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_diff_units_u64(
diff: *const semq_diff_t,
id: u64,
units: *mut u32,
ref_symbols: *mut u8,
cand_symbols: *mut u8,
cap: u64,
count: *mut u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_diff_units_utf8(
diff: *const semq_diff_t,
id: *const u8,
len: u64,
units: *mut u32,
ref_symbols: *mut u8,
cand_symbols: *mut u8,
cap: u64,
count: *mut u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_floor_create(
config: *const semq_config_t,
id_kind: u32,
reference_id: *const u8,
nulls: u64,
changed_rows: u64,
total_rows: u64,
hamming: u64,
out: *mut *mut semq_floor_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_floor_free(floor: *mut semq_floor_t);
pub fn semq_floor_measure(
nulls: *const *const semq_diff_t,
k: u32,
out: *mut *mut semq_floor_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_floor_measure_for(
nulls: *const *const semq_diff_t,
k: u32,
checks: u32,
out: *mut *mut semq_floor_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_floor_config(floor: *const semq_floor_t) -> *const semq_config_t;
pub fn semq_floor_id_kind(floor: *const semq_floor_t) -> u32;
pub fn semq_floor_reference_id(floor: *const semq_floor_t, out: *mut u8);
pub fn semq_floor_nulls(floor: *const semq_floor_t) -> u64;
pub fn semq_floor_changed_rows(floor: *const semq_floor_t) -> u64;
pub fn semq_floor_total_rows(floor: *const semq_floor_t) -> u64;
pub fn semq_floor_hamming(floor: *const semq_floor_t) -> u64;
pub fn semq_floor_max_hamming(floor: *const semq_floor_t) -> u64;
pub fn semq_floor_distinct_nulls(floor: *const semq_floor_t) -> u64;
pub fn semq_floor_json_size(floor: *const semq_floor_t) -> u64;
pub fn semq_floor_save(
floor: *const semq_floor_t,
out: *mut u8,
cap: u64,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_floor_load(
buf: *const u8,
len: u64,
out: *mut *mut semq_floor_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_diff_within(
diff: *const semq_diff_t,
floor: *const semq_floor_t,
out: *mut c_int,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_diff_evaluate(
diff: *const semq_diff_t,
floor: *const semq_floor_t,
checks: u32,
out: *mut *mut semq_verdict_t,
err: *mut semq_error_t,
) -> semq_status_t;
pub fn semq_verdict_free(verdict: *mut semq_verdict_t);
pub fn semq_verdict_passed(verdict: *const semq_verdict_t) -> c_int;
pub fn semq_verdict_reasons(verdict: *const semq_verdict_t) -> u32;
pub fn semq_verdict_row_count(verdict: *const semq_verdict_t) -> u64;
pub fn semq_verdict_row(verdict: *const semq_verdict_t, i: u64) -> u64;
pub fn semq_core_version() -> *const c_char;
pub fn semq_build_id() -> *const c_char;
pub fn semq_backend_name(op: u32) -> *const c_char;
pub fn semq_status_name(status: u32) -> *const c_char;
pub fn semq_sha256(data: *const u8, len: u64, out: *mut u8);
}
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::CStr;
use std::mem::{align_of, offset_of, size_of};
#[test]
fn error_layout_matches_the_abi() {
assert_eq!(size_of::<semq_error_t>(), 152);
assert_eq!(align_of::<semq_error_t>(), 8);
assert_eq!(offset_of!(semq_error_t, status), 0);
assert_eq!(offset_of!(semq_error_t, which), 4);
assert_eq!(offset_of!(semq_error_t, row), 8);
assert_eq!(offset_of!(semq_error_t, field), 16);
assert_eq!(offset_of!(semq_error_t, message), 24);
}
#[test]
fn config_layout_matches_the_abi() {
assert_eq!(size_of::<semq_config_t>(), 16);
assert_eq!(align_of::<semq_config_t>(), 4);
assert_eq!(offset_of!(semq_config_t, op), 0);
assert_eq!(offset_of!(semq_config_t, dim), 4);
assert_eq!(offset_of!(semq_config_t, p1), 8);
assert_eq!(offset_of!(semq_config_t, p2), 12);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn pointer_struct_layouts_match_the_abi() {
assert_eq!(size_of::<semq_pair_t>(), 32);
assert_eq!(offset_of!(semq_pair_t, key), 0);
assert_eq!(offset_of!(semq_pair_t, key_len), 8);
assert_eq!(offset_of!(semq_pair_t, value), 16);
assert_eq!(offset_of!(semq_pair_t, value_len), 24);
assert_eq!(size_of::<semq_ids_t>(), 40);
assert_eq!(offset_of!(semq_ids_t, kind), 0);
assert_eq!(offset_of!(semq_ids_t, n), 8);
assert_eq!(offset_of!(semq_ids_t, u64), 16);
assert_eq!(offset_of!(semq_ids_t, utf8_offsets), 24);
assert_eq!(offset_of!(semq_ids_t, utf8_bytes), 32);
assert_eq!(size_of::<semq_part_t>(), 16);
assert_eq!(offset_of!(semq_part_t, ptr), 0);
assert_eq!(offset_of!(semq_part_t, len), 8);
assert_eq!(size_of::<semq_manifest_change_t>(), 48);
assert_eq!(offset_of!(semq_manifest_change_t, key), 0);
assert_eq!(offset_of!(semq_manifest_change_t, key_len), 8);
assert_eq!(offset_of!(semq_manifest_change_t, has_before), 12);
assert_eq!(offset_of!(semq_manifest_change_t, before), 16);
assert_eq!(offset_of!(semq_manifest_change_t, before_len), 24);
assert_eq!(offset_of!(semq_manifest_change_t, has_after), 28);
assert_eq!(offset_of!(semq_manifest_change_t, after), 32);
assert_eq!(offset_of!(semq_manifest_change_t, after_len), 40);
}
#[test]
fn core_links_and_answers() {
let version = unsafe { CStr::from_ptr(semq_core_version()) };
assert!(!version.to_bytes().is_empty());
let mut cfg = semq_config_t {
op: 0,
dim: 0,
p1: 0,
p2: 0,
};
let status = unsafe { semq_config_quant(4, 4, &mut cfg, std::ptr::null_mut()) };
assert_eq!(status, SEMQ_OK);
assert_eq!(
cfg,
semq_config_t {
op: SEMQ_QUANT,
dim: 4,
p1: 4,
p2: SEMQ_RULE_REVISION
}
);
let mut bytes = [0u8; 13];
unsafe { semq_config_to_bytes(&cfg, bytes.as_mut_ptr()) };
assert_eq!(bytes, [2, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0]);
let name = unsafe { CStr::from_ptr(semq_status_name(SEMQ_ERR_INVALID_INPUT)) };
assert_eq!(name.to_str().unwrap(), "invalid_input");
}
}