use crate::ffi::errors::{ErrorHandle, Status};
use crate::ffi::{Buffer, Slice};
use crate::models::{Role, Version};
use crate::protocol::quic::{QUICStreamID, Varint};
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_varint_maximum() -> u64 {
Varint::MAXIMUM
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_varint_max_size() -> usize {
Varint::MAX_SIZE
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_varint_len(value: u64) -> usize {
Varint::len(value)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_varint_encode(value: u64) -> Buffer {
let mut out = Vec::with_capacity(Varint::len(value));
Varint::encode(&mut out, value);
Buffer::new(out)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_varint_decode(data: *const u8, data_len: usize, out: *mut u64, read: *mut usize) -> bool {
let data = unsafe { Slice::borrow(data, data_len) }.unwrap_or_default();
let (consumed, value) = Varint::decode(data);
if consumed == 0 {
return false;
}
if !out.is_null() {
unsafe { *out = value };
}
if !read.is_null() {
unsafe { *read = consumed };
}
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_varint_only(payload: *const u8, payload_len: usize, name: *const u8, name_len: usize, out: *mut u64, error: *mut *mut ErrorHandle) -> Status {
let Some(name) = (unsafe { Slice::borrow_text(name, name_len) }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
let payload = unsafe { Slice::borrow(payload, payload_len) }.unwrap_or_default();
match Varint::only(payload, name) {
Ok(value) => {
if !out.is_null() {
unsafe { *out = value };
}
Status::Ok
}
Err(failure) => unsafe { ErrorHandle::report(error, &failure) },
}
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_quic_stream_step() -> u64 {
QUICStreamID::STEP
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_quic_stream_is_bidi(stream_id: u64) -> bool {
QUICStreamID::is_bidi(stream_id)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_quic_stream_is_uni(stream_id: u64) -> bool {
QUICStreamID::is_uni(stream_id)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_quic_stream_client_initiated(stream_id: u64) -> bool {
QUICStreamID::client_initiated(stream_id)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_quic_stream_first_bidi(role: i32) -> u64 {
let Some(role) = Role::from_code(role) else {
return u64::MAX;
};
QUICStreamID::first_bidi(role)
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_quic_stream_first_uni(role: i32) -> u64 {
let Some(role) = Role::from_code(role) else {
return u64::MAX;
};
QUICStreamID::first_uni(role)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_quic_handshake_negotiated(alpn: *const u8, alpn_len: usize, versions: *const Version, count: usize, out: *mut Version, error: *mut *mut ErrorHandle) -> Status {
let Some(versions) = (unsafe { Version::borrow_all(versions, count) }) else {
return unsafe { ErrorHandle::raise(error, Status::Invalid) };
};
let alpn = unsafe { Slice::borrow(alpn, alpn_len) }.unwrap_or_default().to_vec();
let handshake = crate::protocol::quic::Handshake { alpn, version: 0 };
match handshake.negotiated(versions) {
Ok(version) => {
if !out.is_null() {
unsafe { *out = version };
}
Status::Ok
}
Err(failure) => unsafe { ErrorHandle::report(error, &failure) },
}
}
#[unsafe(no_mangle)]
pub extern "C" fn soyokaze_quic_handshake_security(quic_version: u32) -> crate::ffi::tls::Security {
let handshake = crate::protocol::quic::Handshake { alpn: Vec::new(), version: quic_version };
crate::ffi::tls::Security::build(&handshake.security())
}