use std::{mem, ptr, slice, str};
use sql_dialect_fmt_formatter::{format, FormatOptions};
static mut LAST_RESULT_PTR: *mut u8 = ptr::null_mut();
static mut LAST_RESULT_LEN: u32 = 0;
#[no_mangle]
pub extern "C" fn sql_dialect_fmt_alloc(len: u32) -> u32 {
let mut buffer = Vec::<u8>::with_capacity(len as usize);
let ptr = buffer.as_mut_ptr();
mem::forget(buffer);
ptr as u32
}
#[no_mangle]
pub unsafe extern "C" fn sql_dialect_fmt_dealloc(ptr: u32, capacity: u32) {
if ptr == 0 || capacity == 0 {
return;
}
drop(Vec::from_raw_parts(ptr as *mut u8, 0, capacity as usize));
}
#[no_mangle]
pub unsafe extern "C" fn sql_dialect_fmt_format(
ptr: u32,
len: u32,
line_width: u32,
indent_width: u32,
uppercase_keywords: u32,
) -> u32 {
clear_last_result();
let bytes = slice::from_raw_parts(ptr as *const u8, len as usize);
let Ok(source) = str::from_utf8(bytes) else {
return 1;
};
let options = FormatOptions::default()
.with_line_width(line_width.max(1) as usize)
.with_indent_width(indent_width.clamp(1, 16) as usize)
.with_uppercase_keywords(uppercase_keywords != 0);
let mut result = format(source, &options).into_bytes().into_boxed_slice();
LAST_RESULT_LEN = result.len() as u32;
LAST_RESULT_PTR = result.as_mut_ptr();
mem::forget(result);
0
}
#[no_mangle]
pub unsafe extern "C" fn sql_dialect_fmt_result_ptr() -> u32 {
LAST_RESULT_PTR as u32
}
#[no_mangle]
pub unsafe extern "C" fn sql_dialect_fmt_result_len() -> u32 {
LAST_RESULT_LEN
}
#[no_mangle]
pub unsafe extern "C" fn sql_dialect_fmt_clear_result() {
clear_last_result();
}
unsafe fn clear_last_result() {
if !LAST_RESULT_PTR.is_null() {
let len = LAST_RESULT_LEN as usize;
if len > 0 {
drop(Box::from_raw(ptr::slice_from_raw_parts_mut(
LAST_RESULT_PTR,
len,
)));
}
LAST_RESULT_PTR = ptr::null_mut();
LAST_RESULT_LEN = 0;
}
}