use crate::errors::Error;
use crate::ffi::errors::{ErrorHandle, Status};
use crate::ffi::helpers::fields::{Field, Fields};
use crate::ffi::{Buffer, Slice};
use crate::helpers::fields::HeaderField;
use crate::helpers::qpack::{Decoder, DecoderInstruction, DynamicTable, Encoder, EncoderInstruction, Prefix, StaticTable};
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_encoder_new() -> *mut Encoder {
Box::into_raw(Box::new(Encoder::new()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_free(encoder: *mut Encoder) {
if !encoder.is_null() {
drop(unsafe { Box::from_raw(encoder) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_set_max_capacity(encoder: *mut Encoder, max_capacity: usize, instructions: *mut Buffer) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
if instructions.is_null() {
return false;
}
unsafe {
*instructions = match encoder.set_max_capacity(max_capacity) {
Some(instruction) => Buffer::new(instruction.encode()),
None => Buffer::EMPTY,
};
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_set_capacity_limit(encoder: *mut Encoder, capacity_limit: usize, instructions: *mut Buffer) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
if instructions.is_null() {
return false;
}
unsafe {
*instructions = match encoder.set_capacity_limit(capacity_limit) {
Some(instruction) => Buffer::new(instruction.encode()),
None => Buffer::EMPTY,
};
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_set_max_outstanding_sections(encoder: *mut Encoder, max_sections: usize) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
encoder.set_max_outstanding_sections(max_sections);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_set_max_instruction_size(encoder: *mut Encoder, max_size: usize) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
encoder.set_max_instruction_size(max_size);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encode(encoder: *mut Encoder, stream_id: u64, fields: *const Field, field_count: usize, block: *mut Buffer, instructions: *mut Buffer) -> bool {
let (Some(encoder), Some(fields)) = (unsafe { encoder.as_mut() }, unsafe { Field::parse_all(fields, field_count) }) else {
return false;
};
if block.is_null() || instructions.is_null() {
return false;
}
let encoded = encoder.encode(stream_id, &fields);
let stream = encoder.take_encoder_stream();
unsafe {
*block = Buffer::new(encoded);
*instructions = if stream.is_empty() { Buffer::EMPTY } else { Buffer::new(stream) };
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_on_decoder_instructions(encoder: *mut Encoder, data: *const u8, data_len: usize, error: *mut *mut ErrorHandle) -> Status {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
let Some(data) = (unsafe { Slice::borrow(data, data_len) }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
match encoder.on_decoder_stream(data) {
Ok(()) => Status::Ok,
Err(failure) => unsafe { ErrorHandle::report(error, &Error::from(failure)) },
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_cancel(encoder: *mut Encoder, stream_id: u64) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
encoder.cancel(stream_id);
true
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_decoder_new() -> *mut Decoder {
Box::into_raw(Box::new(Decoder::new()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_free(decoder: *mut Decoder) {
if !decoder.is_null() {
drop(unsafe { Box::from_raw(decoder) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_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_qpack_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_qpack_decoder_set_max_instruction_size(decoder: *mut Decoder, max_size: usize) -> bool {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return false;
};
decoder.set_max_instruction_size(max_size);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_set_max_blocked_streams(decoder: *mut Decoder, max_streams: usize) -> bool {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return false;
};
decoder.set_max_blocked_streams(max_streams);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_on_encoder_instructions(decoder: *mut Decoder, data: *const u8, data_len: usize, instructions: *mut Buffer, error: *mut *mut ErrorHandle) -> Status {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
let Some(data) = (unsafe { Slice::borrow(data, data_len) }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
if instructions.is_null() {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
}
if let Err(failure) = decoder.on_encoder_stream(data) {
return unsafe { ErrorHandle::report(error, &Error::from(failure)) };
}
let stream = decoder.take_decoder_stream();
unsafe { *instructions = if stream.is_empty() { Buffer::EMPTY } else { Buffer::new(stream) } };
Status::Ok
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decode(decoder: *mut Decoder, stream_id: u64, block: *const u8, block_len: usize, out: *mut *mut Fields, instructions: *mut Buffer, error: *mut *mut ErrorHandle) -> Status {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
if out.is_null() || instructions.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(stream_id, block) {
Ok((fields, answer)) => {
unsafe {
*out = Box::into_raw(Box::new(Fields(fields)));
*instructions = match answer {
Some(answer) => Buffer::new(answer.encode()),
None => Buffer::EMPTY,
};
}
Status::Ok
}
Err(failure) => unsafe { ErrorHandle::report(error, &Error::from(failure)) },
}
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_capacity() -> usize {
DynamicTable::DEFAULT_CAPACITY
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_capacity_limit() -> usize {
Encoder::DEFAULT_CAPACITY_LIMIT
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_max_outstanding_sections() -> usize {
Encoder::DEFAULT_MAX_OUTSTANDING_SECTIONS
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_max_instruction_size() -> usize {
Encoder::DEFAULT_MAX_INSTRUCTION_SIZE
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_idle_capacity() -> usize {
Encoder::DEFAULT_IDLE_CAPACITY
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_max_capacity() -> usize {
Decoder::DEFAULT_MAX_CAPACITY
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_max_decoded_size() -> usize {
Decoder::DEFAULT_MAX_DECODED_SIZE
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_default_max_blocked_streams() -> usize {
Decoder::DEFAULT_MAX_BLOCKED_STREAMS
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_static_count() -> usize {
StaticTable::entries().len()
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_static_base() -> usize {
0
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_static_name(index: usize) -> Slice {
Slice::maybe(StaticTable::entries().get(index).map(|field| field.name.as_str()))
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_static_value(index: usize) -> Slice {
Slice::maybe(StaticTable::entries().get(index).map(|field| field.value.as_str()))
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_static_index() -> *const crate::ffi::helpers::fields::Index {
StaticTable::index()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_static_find(name: *const u8, name_len: usize, value: *const u8, value_len: usize, out: *mut u64, 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(&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_qpack_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_qpack_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_qpack_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_qpack_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_qpack_table_inserted_count(table: *const DynamicTable) -> u64 {
unsafe { table.as_ref() }.map_or(0, |table| table.inserted_count())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_table_name(table: *const DynamicTable, absolute_index: u64) -> Slice {
Slice::maybe(unsafe { table.as_ref() }.and_then(|table| table.get(absolute_index)).map(|field| field.name.as_str()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_table_value(table: *const DynamicTable, absolute_index: u64) -> Slice {
Slice::maybe(unsafe { table.as_ref() }.and_then(|table| table.get(absolute_index)).map(|field| field.value.as_str()))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_table_fits(table: *const DynamicTable, name: *const u8, name_len: usize, value: *const u8, value_len: usize) -> 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;
};
table.fits(&HeaderField::new(name, value))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_table_relative(table: *const DynamicTable, index: u64) -> i64 {
match unsafe { table.as_ref() }.and_then(|table| table.relative(index)) {
Some(relative) => relative as i64,
None => -1,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_table_indexed(table: *const DynamicTable, base: u64, index: u64) -> i64 {
match unsafe { table.as_ref() }.and_then(|table| table.indexed(base, index)) {
Some(absolute) => absolute as i64,
None => -1,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_table_post_base(table: *const DynamicTable, base: u64, index: u64) -> i64 {
match unsafe { table.as_ref() }.and_then(|table| table.post_base(base, index)) {
Some(absolute) => absolute as i64,
None => -1,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_table_find(table: *const DynamicTable, name: *const u8, name_len: usize, value: *const u8, value_len: usize, out: *mut u64, 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(&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_qpack_table_probe(table: *const DynamicTable, name: *const u8, name_len: usize, value: *const u8, value_len: usize, below: u64, out: *mut u64, exact: *mut bool, blocked: *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 (matched, above) = table.probe(&HeaderField::new(name, value), below);
if !blocked.is_null() {
unsafe { *blocked = above };
}
let Some((index, exactly)) = matched else {
return false;
};
if !out.is_null() {
unsafe { *out = index };
}
if !exact.is_null() {
unsafe { *exact = exactly };
}
true
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_prefix_max_entries(max_capacity: usize) -> u64 {
Prefix::max_entries(max_capacity)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_prefix_relative(base: u64, absolute: u64) -> u64 {
Prefix::relative(base, absolute)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_prefix_encode_insert_count(required: u64, max_capacity: usize) -> u64 {
Prefix::encode_insert_count(required, max_capacity)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_prefix_decode_insert_count(encoded: u64, inserted: u64, max_capacity: usize, out: *mut u64) -> bool {
let Ok(required) = Prefix::decode_insert_count(encoded, inserted, max_capacity) else {
return false;
};
if !out.is_null() {
unsafe { *out = required };
}
true
}
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum EncoderInstructionKind {
SetDynamicTableCapacity = 0,
InsertWithNameReference = 1,
InsertWithLiteralName = 2,
Duplicate = 3,
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_encoder_instruction_set_capacity(capacity: usize) -> *mut EncoderInstruction {
Box::into_raw(Box::new(EncoderInstruction::SetDynamicTableCapacity { capacity }))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_insert_with_name_reference(from_static: bool, name_index: u64, value: *const u8, value_len: usize) -> *mut EncoderInstruction {
let value = unsafe { Slice::borrow(value, value_len) }.unwrap_or_default().to_vec();
Box::into_raw(Box::new(EncoderInstruction::InsertWithNameReference { from_static, name_index, value }))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_insert_with_literal_name(name: *const u8, name_len: usize, value: *const u8, value_len: usize) -> *mut EncoderInstruction {
let name = unsafe { Slice::borrow(name, name_len) }.unwrap_or_default().to_vec();
let value = unsafe { Slice::borrow(value, value_len) }.unwrap_or_default().to_vec();
Box::into_raw(Box::new(EncoderInstruction::InsertWithLiteralName { name, value }))
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_encoder_instruction_duplicate(index: u64) -> *mut EncoderInstruction {
Box::into_raw(Box::new(EncoderInstruction::Duplicate { index }))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_free(instruction: *mut EncoderInstruction) {
if !instruction.is_null() {
drop(unsafe { Box::from_raw(instruction) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_kind(instruction: *const EncoderInstruction) -> EncoderInstructionKind {
match unsafe { instruction.as_ref() } {
Some(EncoderInstruction::SetDynamicTableCapacity { .. }) | None => EncoderInstructionKind::SetDynamicTableCapacity,
Some(EncoderInstruction::InsertWithNameReference { .. }) => EncoderInstructionKind::InsertWithNameReference,
Some(EncoderInstruction::InsertWithLiteralName { .. }) => EncoderInstructionKind::InsertWithLiteralName,
Some(EncoderInstruction::Duplicate { .. }) => EncoderInstructionKind::Duplicate,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_capacity(instruction: *const EncoderInstruction) -> usize {
match unsafe { instruction.as_ref() } {
Some(EncoderInstruction::SetDynamicTableCapacity { capacity }) => *capacity,
_ => 0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_from_static(instruction: *const EncoderInstruction) -> bool {
match unsafe { instruction.as_ref() } {
Some(EncoderInstruction::InsertWithNameReference { from_static, .. }) => *from_static,
_ => false,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_index(instruction: *const EncoderInstruction) -> u64 {
match unsafe { instruction.as_ref() } {
Some(EncoderInstruction::InsertWithNameReference { name_index, .. }) => *name_index,
Some(EncoderInstruction::Duplicate { index }) => *index,
_ => 0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_name(instruction: *const EncoderInstruction) -> Slice {
match unsafe { instruction.as_ref() } {
Some(EncoderInstruction::InsertWithLiteralName { name, .. }) => Slice::new(name),
_ => Slice::ABSENT,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_value(instruction: *const EncoderInstruction) -> Slice {
match unsafe { instruction.as_ref() } {
Some(EncoderInstruction::InsertWithNameReference { value, .. }) => Slice::new(value),
Some(EncoderInstruction::InsertWithLiteralName { value, .. }) => Slice::new(value),
_ => Slice::ABSENT,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_encode(instruction: *const EncoderInstruction) -> Buffer {
match unsafe { instruction.as_ref() } {
Some(instruction) => Buffer::new(instruction.encode()),
None => Buffer::EMPTY,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_instruction_decode(data: *const u8, data_len: usize, out: *mut *mut EncoderInstruction, read: *mut usize, error: *mut *mut ErrorHandle) -> Status {
let Some(data) = (unsafe { Slice::borrow(data, data_len) }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
match EncoderInstruction::decode(data) {
Ok((consumed, instruction)) => {
if !out.is_null() {
unsafe { *out = Box::into_raw(Box::new(instruction)) };
}
if !read.is_null() {
unsafe { *read = consumed };
}
Status::Ok
}
Err(failure) => unsafe { ErrorHandle::report(error, &Error::from(failure)) },
}
}
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum DecoderInstructionKind {
SectionAcknowledgment = 0,
StreamCancellation = 1,
InsertCountIncrement = 2,
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_decoder_instruction_section_acknowledgment(stream_id: u64) -> *mut DecoderInstruction {
Box::into_raw(Box::new(DecoderInstruction::SectionAcknowledgment { stream_id }))
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_decoder_instruction_stream_cancellation(stream_id: u64) -> *mut DecoderInstruction {
Box::into_raw(Box::new(DecoderInstruction::StreamCancellation { stream_id }))
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_qpack_decoder_instruction_insert_count_increment(increment: u64) -> *mut DecoderInstruction {
Box::into_raw(Box::new(DecoderInstruction::InsertCountIncrement { increment }))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_instruction_free(instruction: *mut DecoderInstruction) {
if !instruction.is_null() {
drop(unsafe { Box::from_raw(instruction) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_instruction_kind(instruction: *const DecoderInstruction) -> DecoderInstructionKind {
match unsafe { instruction.as_ref() } {
Some(DecoderInstruction::SectionAcknowledgment { .. }) | None => DecoderInstructionKind::SectionAcknowledgment,
Some(DecoderInstruction::StreamCancellation { .. }) => DecoderInstructionKind::StreamCancellation,
Some(DecoderInstruction::InsertCountIncrement { .. }) => DecoderInstructionKind::InsertCountIncrement,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_instruction_stream_id(instruction: *const DecoderInstruction) -> u64 {
match unsafe { instruction.as_ref() } {
Some(DecoderInstruction::SectionAcknowledgment { stream_id }) => *stream_id,
Some(DecoderInstruction::StreamCancellation { stream_id }) => *stream_id,
_ => 0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_instruction_increment(instruction: *const DecoderInstruction) -> u64 {
match unsafe { instruction.as_ref() } {
Some(DecoderInstruction::InsertCountIncrement { increment }) => *increment,
_ => 0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_instruction_encode(instruction: *const DecoderInstruction) -> Buffer {
match unsafe { instruction.as_ref() } {
Some(instruction) => Buffer::new(instruction.encode()),
None => Buffer::EMPTY,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_instruction_decode(data: *const u8, data_len: usize, out: *mut *mut DecoderInstruction, read: *mut usize, error: *mut *mut ErrorHandle) -> Status {
let Some(data) = (unsafe { Slice::borrow(data, data_len) }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
match DecoderInstruction::decode(data) {
Ok((consumed, instruction)) => {
if !out.is_null() {
unsafe { *out = Box::into_raw(Box::new(instruction)) };
}
if !read.is_null() {
unsafe { *read = consumed };
}
Status::Ok
}
Err(failure) => unsafe { ErrorHandle::report(error, &Error::from(failure)) },
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_queue(encoder: *mut Encoder, instructions: *mut *mut EncoderInstruction, count: usize) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
if instructions.is_null() {
return count == 0;
}
let mut queued = Vec::with_capacity(count);
for index in 0..count {
let handle = unsafe { *instructions.add(index) };
if handle.is_null() {
return false;
}
queued.push(*unsafe { Box::from_raw(handle) });
}
encoder.queue(&queued);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_stream(encoder: *const Encoder) -> Slice {
match unsafe { encoder.as_ref() } {
Some(encoder) => Slice::new(encoder.encoder_stream()),
None => Slice::ABSENT,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_take_stream(encoder: *mut Encoder) -> Buffer {
match unsafe { encoder.as_mut() } {
Some(encoder) => Buffer::new(encoder.take_encoder_stream()),
None => Buffer::EMPTY,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_reclaim_stream(encoder: *mut Encoder, buffer: Buffer) -> bool {
let octets = match buffer.data.is_null() {
true => Vec::new(),
false => unsafe { Vec::from_raw_parts(buffer.data, buffer.len, buffer.capacity) },
};
match unsafe { encoder.as_mut() } {
Some(encoder) => {
encoder.reclaim_encoder_stream(octets);
true
}
None => false,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_set_idle_capacity(encoder: *mut Encoder, idle_capacity: usize) -> bool {
let Some(encoder) = (unsafe { encoder.as_mut() }) else {
return false;
};
encoder.set_idle_capacity(idle_capacity);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_outstanding(encoder: *const Encoder) -> usize {
unsafe { encoder.as_ref() }.map_or(0, |encoder| encoder.outstanding())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_known_received_count(encoder: *const Encoder) -> u64 {
unsafe { encoder.as_ref() }.map_or(0, |encoder| encoder.known_received_count())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_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_qpack_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_qpack_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_qpack_encoder_reference(encoder: *const Encoder, name: *const u8, name_len: usize, value: *const u8, value_len: usize, from_static: *mut bool, out: *mut u64, 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((statically, index, matched)) = encoder.reference(&HeaderField::new(name, value)) else {
return false;
};
if !from_static.is_null() {
unsafe { *from_static = statically };
}
if !out.is_null() {
unsafe { *out = index };
}
if !exact.is_null() {
unsafe { *exact = matched };
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_encoder_on_decoder_instruction(encoder: *mut Encoder, instruction: *mut DecoderInstruction) -> bool {
if instruction.is_null() {
return false;
}
let instruction = *unsafe { Box::from_raw(instruction) };
match unsafe { encoder.as_mut() } {
Some(encoder) => {
encoder.on_decoder_instruction(instruction);
true
}
None => false,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_queue(decoder: *mut Decoder, instructions: *mut *mut DecoderInstruction, count: usize) -> bool {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return false;
};
if instructions.is_null() {
return count == 0;
}
let mut queued = Vec::with_capacity(count);
for index in 0..count {
let handle = unsafe { *instructions.add(index) };
if handle.is_null() {
return false;
}
queued.push(*unsafe { Box::from_raw(handle) });
}
decoder.queue(&queued);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_stream(decoder: *const Decoder) -> Slice {
match unsafe { decoder.as_ref() } {
Some(decoder) => Slice::new(decoder.decoder_stream()),
None => Slice::ABSENT,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_take_stream(decoder: *mut Decoder) -> Buffer {
match unsafe { decoder.as_mut() } {
Some(decoder) => Buffer::new(decoder.take_decoder_stream()),
None => Buffer::EMPTY,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_reclaim_stream(decoder: *mut Decoder, buffer: Buffer) -> bool {
let octets = match buffer.data.is_null() {
true => Vec::new(),
false => unsafe { Vec::from_raw_parts(buffer.data, buffer.len, buffer.capacity) },
};
match unsafe { decoder.as_mut() } {
Some(decoder) => {
decoder.reclaim_decoder_stream(octets);
true
}
None => false,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_set_idle_capacity(decoder: *mut Decoder, idle_capacity: usize) -> bool {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return false;
};
decoder.set_idle_capacity(idle_capacity);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_blocked(decoder: *const Decoder) -> usize {
unsafe { decoder.as_ref() }.map_or(0, |decoder| decoder.blocked())
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_unblocked(decoder: *const Decoder) -> Buffer {
let Some(decoder) = (unsafe { decoder.as_ref() }) else {
return Buffer::EMPTY;
};
let streams = decoder.unblocked();
let mut octets = Vec::with_capacity(streams.len() * size_of::<u64>());
for stream_id in streams {
octets.extend_from_slice(&stream_id.to_ne_bytes());
}
Buffer::new(octets)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_cancel(decoder: *mut Decoder, stream_id: u64) -> bool {
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return false;
};
decoder.cancel(stream_id);
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_on_encoder_instruction(decoder: *mut Decoder, instruction: *mut EncoderInstruction, out: *mut *mut DecoderInstruction, error: *mut *mut ErrorHandle) -> Status {
if instruction.is_null() {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
}
let instruction = *unsafe { Box::from_raw(instruction) };
let Some(decoder) = (unsafe { decoder.as_mut() }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
match decoder.on_encoder_instruction(instruction) {
Ok(answer) => {
if !out.is_null() {
unsafe {
*out = match answer {
Some(answer) => Box::into_raw(Box::new(answer)),
None => std::ptr::null_mut(),
}
};
}
Status::Ok
}
Err(failure) => unsafe { ErrorHandle::report(error, &Error::from(failure)) },
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_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_qpack_decoder_resolve(decoder: *const Decoder, from_static: bool, base: u64, index: u64, name: *mut Buffer, value: *mut Buffer) -> bool {
let Some(decoder) = (unsafe { decoder.as_ref() }) else {
return false;
};
let Ok(field) = decoder.resolve(from_static, base, index) else {
return false;
};
if !name.is_null() {
unsafe { *name = Buffer::new(field.name.into_bytes()) };
}
if !value.is_null() {
unsafe { *value = Buffer::new(field.value.into_bytes()) };
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_qpack_decoder_resolve_name(decoder: *const Decoder, from_static: bool, base: u64, index: u64) -> Buffer {
let Some(decoder) = (unsafe { decoder.as_ref() }) else {
return Buffer::EMPTY;
};
match decoder.resolve_name(from_static, base, index) {
Ok(name) => Buffer::new(name.into_bytes()),
Err(_) => Buffer::EMPTY,
}
}