use crate::ffi::errors::{ErrorHandle, Status};
use crate::ffi::helpers::fields::{Field, Fields};
use crate::ffi::{Buffer, Slice};
use crate::helpers::hpack::{Decoder, DynamicTable, Encoder, StaticTable};
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_default_capacity() -> usize {
DynamicTable::DEFAULT_CAPACITY
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_default_capacity_limit() -> usize {
Encoder::DEFAULT_CAPACITY_LIMIT
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_default_max_decoded_size() -> usize {
Decoder::DEFAULT_MAX_DECODED_SIZE
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_static_count() -> usize {
StaticTable::entries().len()
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_static_base() -> usize {
1
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_static_name(index: usize) -> Slice {
Slice::maybe(index.checked_sub(1).and_then(|offset| StaticTable::entries().get(offset)).map(|field| field.name.as_str()))
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_static_value(index: usize) -> Slice {
Slice::maybe(index.checked_sub(1).and_then(|offset| StaticTable::entries().get(offset)).map(|field| field.value.as_str()))
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_static_index() -> *const crate::ffi::helpers::fields::Index {
StaticTable::index()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_static_find(name: *const u8, name_len: usize, value: *const u8, value_len: usize, out: *mut usize, exact: *mut bool) -> bool {
let (Some(name), Some(value)) = (unsafe { Slice::borrow_text(name, name_len) }, unsafe { Slice::borrow_text(value, value_len) }) else {
return false;
};
let Some((index, matched)) = StaticTable::find(&crate::helpers::fields::HeaderField::new(name, value)) else {
return false;
};
if !out.is_null() {
unsafe { *out = index };
}
if !exact.is_null() {
unsafe { *exact = matched };
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_table_size(table: *const DynamicTable) -> usize {
unsafe { table.as_ref() }.map_or(0, |table| table.size())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_table_capacity(table: *const DynamicTable) -> usize {
unsafe { table.as_ref() }.map_or(0, |table| table.capacity())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_table_len(table: *const DynamicTable) -> usize {
unsafe { table.as_ref() }.map_or(0, |table| table.len())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_table_is_empty(table: *const DynamicTable) -> bool {
unsafe { table.as_ref() }.is_none_or(|table| table.is_empty())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_table_name(table: *const DynamicTable, index: usize) -> Slice {
Slice::maybe(unsafe { table.as_ref() }.and_then(|table| table.get(index)).map(|field| field.name.as_str()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_table_value(table: *const DynamicTable, index: usize) -> Slice {
Slice::maybe(unsafe { table.as_ref() }.and_then(|table| table.get(index)).map(|field| field.value.as_str()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_table_find(table: *const DynamicTable, name: *const u8, name_len: usize, value: *const u8, value_len: usize, out: *mut usize, exact: *mut bool) -> bool {
let (Some(table), Some(name), Some(value)) = (unsafe { table.as_ref() }, unsafe { Slice::borrow_text(name, name_len) }, unsafe { Slice::borrow_text(value, value_len) }) else {
return false;
};
let Some((index, matched)) = table.find(&crate::helpers::fields::HeaderField::new(name, value)) else {
return false;
};
if !out.is_null() {
unsafe { *out = index };
}
if !exact.is_null() {
unsafe { *exact = matched };
}
true
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_encoder_new() -> *mut Encoder {
Box::into_raw(Box::new(Encoder::new()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encoder_free(encoder: *mut Encoder) {
if !encoder.is_null() {
drop(unsafe { Box::from_raw(encoder) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encoder_set_max_capacity(encoder: *mut Encoder, max_capacity: usize) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
encoder.set_max_capacity(max_capacity);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encoder_set_capacity_limit(encoder: *mut Encoder, capacity_limit: usize) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
encoder.set_capacity_limit(capacity_limit);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encode(encoder: *mut Encoder, fields: *const Field, field_count: usize) -> Buffer {
let (Some(encoder), Some(fields)) = (unsafe { encoder.as_mut() }, unsafe { Field::parse_all(fields, field_count) }) else {
return Buffer::EMPTY;
};
Buffer::new(encoder.encode(&fields))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encoder_capacity_limit(encoder: *const Encoder) -> usize {
unsafe { encoder.as_ref() }.map_or(0, |encoder| encoder.capacity_limit())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encoder_max_capacity(encoder: *const Encoder) -> usize {
unsafe { encoder.as_ref() }.map_or(0, |encoder| encoder.max_capacity())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encoder_table(encoder: *const Encoder) -> *const DynamicTable {
match unsafe { encoder.as_ref() } {
Some(encoder) => encoder.dynamic_table(),
None => std::ptr::null(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encoder_reference(encoder: *const Encoder, name: *const u8, name_len: usize, value: *const u8, value_len: usize, out: *mut usize, exact: *mut bool) -> bool {
let (Some(encoder), Some(name), Some(value)) = (unsafe { encoder.as_ref() }, unsafe { Slice::borrow_text(name, name_len) }, unsafe { Slice::borrow_text(value, value_len) }) else {
return false;
};
let Some((index, matched)) = encoder.reference(&crate::helpers::fields::HeaderField::new(name, value)) else {
return false;
};
if !out.is_null() {
unsafe { *out = index };
}
if !exact.is_null() {
unsafe { *exact = matched };
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_encode_field(encoder: *mut Encoder, name: *const u8, name_len: usize, value: *const u8, value_len: usize) -> Buffer {
let (Some(encoder), Some(name), Some(value)) = (unsafe { encoder.as_mut() }, unsafe { Slice::borrow_text(name, name_len) }, unsafe { Slice::borrow_text(value, value_len) }) else {
return Buffer::EMPTY;
};
let mut out = Vec::new();
encoder.encode_field(&mut out, &crate::helpers::fields::HeaderField::new(name, value));
Buffer::new(out)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_hpack_decoder_new() -> *mut Decoder {
Box::into_raw(Box::new(Decoder::new()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_decoder_free(decoder: *mut Decoder) {
if !decoder.is_null() {
drop(unsafe { Box::from_raw(decoder) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_decoder_set_max_decoded_size(decoder: *mut Decoder, max_size: usize) -> bool {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return false;
};
decoder.set_max_decoded_size(max_size);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_decoder_set_max_capacity(decoder: *mut Decoder, max_capacity: usize) -> bool {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return false;
};
decoder.set_max_capacity(max_capacity);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_decode(decoder: *mut Decoder, block: *const u8, block_len: usize, out: *mut *mut Fields, error: *mut *mut ErrorHandle) -> Status {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
if out.is_null() {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
}
let Some(block) = (unsafe { Slice::borrow(block, block_len) }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
match decoder.decode(block) {
Ok(fields) => {
unsafe { *out = Box::into_raw(Box::new(Fields(fields))) };
Status::Ok
}
Err(failure) => unsafe { ErrorHandle::report(error, &crate::errors::Error::from(failure)) },
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_decoder_table(decoder: *const Decoder) -> *const DynamicTable {
match unsafe { decoder.as_ref() } {
Some(decoder) => decoder.dynamic_table(),
None => std::ptr::null(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hpack_decoder_resolve(decoder: *const Decoder, index: u64, name: *mut Slice, value: *mut Slice) -> bool {
let Some(decoder) = (unsafe { decoder.as_ref() }) else {
return false;
};
let Ok(field) = decoder.resolve(index) else {
return false;
};
if !name.is_null() {
unsafe { *name = Slice::text(field.name.as_str()) };
}
if !value.is_null() {
unsafe { *value = Slice::text(field.value.as_str()) };
}
true
}