use crate::ffi::{Buffer, Slice};
use crate::models::{Message, Role};
pub use crate::finalizer::{DateCache, RequestFinalizer, ResponseFinalizer};
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_date_length() -> usize {
crate::finalizer::DATE_LENGTH
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_day_name(index: usize) -> Slice {
Slice::maybe(crate::finalizer::DAY_NAMES.get(index).copied())
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_month_name(index: usize) -> Slice {
Slice::maybe(crate::finalizer::MONTH_NAMES.get(index).copied())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_civil_from_days(days: i64, year: *mut i64, month: *mut u32, day: *mut u32) {
let (civil_year, civil_month, civil_day) = DateCache::civil_from_days(days);
if !year.is_null() {
unsafe { *year = civil_year };
}
if !month.is_null() {
unsafe { *month = civil_month };
}
if !day.is_null() {
unsafe { *day = civil_day };
}
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_http_date(unix_seconds: u64) -> Buffer {
Buffer::new(DateCache::format(unix_seconds).into_bytes())
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_date_cache_new() -> *mut DateCache {
Box::into_raw(Box::new(DateCache::new()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_date_cache_free(cache: *mut DateCache) {
if !cache.is_null() {
drop(unsafe { Box::from_raw(cache) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_date_cache_now(cache: *const DateCache) -> Buffer {
match unsafe { cache.as_ref() } {
Some(cache) => Buffer::new(cache.now().into_bytes()),
None => Buffer::new(DateCache::shared().now().into_bytes()),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_response_finalizer_new(hsts: *const crate::ffi::hsts::HSTSPolicy) -> *mut ResponseFinalizer {
let hsts = unsafe { hsts.as_ref() }.map(|hsts| hsts.parse());
Box::into_raw(Box::new(ResponseFinalizer::new(hsts)))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_response_finalizer_free(finalizer: *mut ResponseFinalizer) {
if !finalizer.is_null() {
drop(unsafe { Box::from_raw(finalizer) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_response_finalizer_finalize(finalizer: *const ResponseFinalizer, role: i32, secure: bool, message: *mut Message) -> bool {
let Some(role) = Role::from_code(role) else {
return false;
};
let (Some(finalizer), Some(message)) = (unsafe { finalizer.as_ref() }, unsafe { message.as_mut() }) else {
return false;
};
finalizer.finalize(role, secure, message);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_request_finalizer_new(authority: *const u8, authority_len: usize) -> *mut RequestFinalizer {
Box::into_raw(Box::new(RequestFinalizer::new(unsafe { Slice::borrow_text(authority, authority_len) })))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_request_finalizer_free(finalizer: *mut RequestFinalizer) {
if !finalizer.is_null() {
drop(unsafe { Box::from_raw(finalizer) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_request_finalizer_authority(finalizer: *const RequestFinalizer) -> Slice {
Slice::maybe(unsafe { finalizer.as_ref() }.and_then(|finalizer| finalizer.authority.as_deref()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_request_finalizer_finalize(finalizer: *const RequestFinalizer, role: i32, message: *mut Message) -> bool {
let Some(role) = Role::from_code(role) else {
return false;
};
let (Some(finalizer), Some(message)) = (unsafe { finalizer.as_ref() }, unsafe { message.as_mut() }) else {
return false;
};
finalizer.finalize(role, message);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_message_finalize_response(message: *mut Message, cache: *const DateCache, hsts: *const crate::ffi::hsts::HSTSPolicy) -> bool {
let Some(message) = (unsafe { message.as_mut() }) else {
return false;
};
let policy = unsafe { hsts.as_ref() }.map(|hsts| hsts.parse());
let cache = unsafe { cache.as_ref() }.unwrap_or_else(|| DateCache::shared());
message.finalize_response(cache, policy.as_ref());
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_message_finalize_request(message: *mut Message, authority: *const u8, authority_len: usize) -> bool {
let Some(message) = (unsafe { message.as_mut() }) else {
return false;
};
message.finalize_request(unsafe { Slice::borrow_text(authority, authority_len) });
true
}