#![allow(dead_code)]
use std::ffi::{CStr, c_char};
use blazen_llm::{
CompletionResponse as CoreCompletionResponse, EmbeddingResponse as CoreEmbeddingResponse,
};
use blazen_uniffi::errors::BlazenError as InnerError;
use blazen_uniffi::llm::{
ChatMessage as InnerChatMessage, CompletionRequest as InnerCompletionRequest,
CompletionResponse as InnerCompletionResponse, EmbeddingResponse as InnerEmbeddingResponse,
Media as InnerMedia, TokenUsage as InnerTokenUsage, Tool as InnerTool,
ToolCall as InnerToolCall,
};
use crate::error::BlazenError;
use crate::string::{alloc_cstring, cstr_to_opt_string, cstr_to_str};
fn write_internal_err(out_err: *mut *mut BlazenError, message: String) {
if out_err.is_null() {
return;
}
unsafe {
*out_err = BlazenError::from(InnerError::Internal { message }).into_ptr();
}
}
unsafe fn read_json_input<'a>(
json: *const c_char,
fn_name: &str,
out_err: *mut *mut BlazenError,
) -> Option<&'a str> {
if json.is_null() {
write_internal_err(out_err, format!("{fn_name}: json pointer is null"));
return None;
}
let cstr = unsafe { CStr::from_ptr(json) };
match cstr.to_str() {
Ok(s) => Some(s),
Err(e) => {
write_internal_err(out_err, format!("{fn_name}: input is not valid UTF-8: {e}"));
None
}
}
}
pub struct BlazenMedia(pub(crate) InnerMedia);
impl BlazenMedia {
pub(crate) fn into_ptr(self) -> *mut BlazenMedia {
Box::into_raw(Box::new(self))
}
}
impl From<InnerMedia> for BlazenMedia {
fn from(inner: InnerMedia) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_media_new(
kind: *const c_char,
mime_type: *const c_char,
data_base64: *const c_char,
) -> *mut BlazenMedia {
let kind = match unsafe { cstr_to_str(kind) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
let mime_type = match unsafe { cstr_to_str(mime_type) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
let data_base64 = match unsafe { cstr_to_str(data_base64) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
BlazenMedia(InnerMedia {
kind,
mime_type,
data_base64,
})
.into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_media_kind(handle: *const BlazenMedia) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
alloc_cstring(&m.0.kind)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_media_mime_type(handle: *const BlazenMedia) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
alloc_cstring(&m.0.mime_type)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_media_data_base64(handle: *const BlazenMedia) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
alloc_cstring(&m.0.data_base64)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_media_free(handle: *mut BlazenMedia) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
pub struct BlazenToolCall(pub(crate) InnerToolCall);
impl BlazenToolCall {
pub(crate) fn into_ptr(self) -> *mut BlazenToolCall {
Box::into_raw(Box::new(self))
}
}
impl From<InnerToolCall> for BlazenToolCall {
fn from(inner: InnerToolCall) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_call_new(
id: *const c_char,
name: *const c_char,
arguments_json: *const c_char,
) -> *mut BlazenToolCall {
let id = match unsafe { cstr_to_str(id) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
let name = match unsafe { cstr_to_str(name) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
let arguments_json = match unsafe { cstr_to_str(arguments_json) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
BlazenToolCall(InnerToolCall {
id,
name,
arguments_json,
})
.into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_call_id(handle: *const BlazenToolCall) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let t = unsafe { &*handle };
alloc_cstring(&t.0.id)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_call_name(handle: *const BlazenToolCall) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let t = unsafe { &*handle };
alloc_cstring(&t.0.name)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_call_arguments_json(
handle: *const BlazenToolCall,
) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let t = unsafe { &*handle };
alloc_cstring(&t.0.arguments_json)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_call_free(handle: *mut BlazenToolCall) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
pub struct BlazenTool(pub(crate) InnerTool);
impl BlazenTool {
pub(crate) fn into_ptr(self) -> *mut BlazenTool {
Box::into_raw(Box::new(self))
}
}
impl From<InnerTool> for BlazenTool {
fn from(inner: InnerTool) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_new(
name: *const c_char,
description: *const c_char,
parameters_json: *const c_char,
) -> *mut BlazenTool {
let name = match unsafe { cstr_to_str(name) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
let description = match unsafe { cstr_to_str(description) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
let parameters_json = match unsafe { cstr_to_str(parameters_json) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
BlazenTool(InnerTool {
name,
description,
parameters_json,
})
.into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_name(handle: *const BlazenTool) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let t = unsafe { &*handle };
alloc_cstring(&t.0.name)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_description(handle: *const BlazenTool) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let t = unsafe { &*handle };
alloc_cstring(&t.0.description)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_parameters_json(handle: *const BlazenTool) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let t = unsafe { &*handle };
alloc_cstring(&t.0.parameters_json)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_tool_free(handle: *mut BlazenTool) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
pub struct BlazenTokenUsage(pub(crate) InnerTokenUsage);
impl BlazenTokenUsage {
pub(crate) fn into_ptr(self) -> *mut BlazenTokenUsage {
Box::into_raw(Box::new(self))
}
}
impl From<InnerTokenUsage> for BlazenTokenUsage {
fn from(inner: InnerTokenUsage) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub extern "C" fn blazen_token_usage_new(
prompt_tokens: u64,
completion_tokens: u64,
total_tokens: u64,
cached_input_tokens: u64,
reasoning_tokens: u64,
) -> *mut BlazenTokenUsage {
BlazenTokenUsage(InnerTokenUsage {
prompt_tokens,
completion_tokens,
total_tokens,
cached_input_tokens,
reasoning_tokens,
})
.into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_token_usage_prompt_tokens(handle: *const BlazenTokenUsage) -> u64 {
if handle.is_null() {
return 0;
}
let u = unsafe { &*handle };
u.0.prompt_tokens
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_token_usage_completion_tokens(
handle: *const BlazenTokenUsage,
) -> u64 {
if handle.is_null() {
return 0;
}
let u = unsafe { &*handle };
u.0.completion_tokens
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_token_usage_total_tokens(handle: *const BlazenTokenUsage) -> u64 {
if handle.is_null() {
return 0;
}
let u = unsafe { &*handle };
u.0.total_tokens
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_token_usage_cached_input_tokens(
handle: *const BlazenTokenUsage,
) -> u64 {
if handle.is_null() {
return 0;
}
let u = unsafe { &*handle };
u.0.cached_input_tokens
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_token_usage_reasoning_tokens(
handle: *const BlazenTokenUsage,
) -> u64 {
if handle.is_null() {
return 0;
}
let u = unsafe { &*handle };
u.0.reasoning_tokens
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_token_usage_free(handle: *mut BlazenTokenUsage) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
pub struct BlazenChatMessage(pub(crate) InnerChatMessage);
impl BlazenChatMessage {
pub(crate) fn into_ptr(self) -> *mut BlazenChatMessage {
Box::into_raw(Box::new(self))
}
}
impl From<InnerChatMessage> for BlazenChatMessage {
fn from(inner: InnerChatMessage) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_new(
role: *const c_char,
content: *const c_char,
) -> *mut BlazenChatMessage {
let role = match unsafe { cstr_to_str(role) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
let content = match unsafe { cstr_to_str(content) } {
Some(s) => s.to_owned(),
None => return std::ptr::null_mut(),
};
BlazenChatMessage(InnerChatMessage {
role,
content,
media_parts: Vec::new(),
tool_calls: Vec::new(),
tool_call_id: None,
name: None,
})
.into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_role(handle: *const BlazenChatMessage) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
alloc_cstring(&m.0.role)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_content(
handle: *const BlazenChatMessage,
) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
alloc_cstring(&m.0.content)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_media_parts_push(
handle: *mut BlazenChatMessage,
media: *mut BlazenMedia,
) {
if media.is_null() {
return;
}
let media_box = unsafe { Box::from_raw(media) };
if handle.is_null() {
drop(media_box);
return;
}
let m = unsafe { &mut *handle };
m.0.media_parts.push(media_box.0);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_media_parts_count(
handle: *const BlazenChatMessage,
) -> usize {
if handle.is_null() {
return 0;
}
let m = unsafe { &*handle };
m.0.media_parts.len()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_media_parts_get(
handle: *const BlazenChatMessage,
idx: usize,
) -> *mut BlazenMedia {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
match m.0.media_parts.get(idx) {
Some(media) => BlazenMedia(media.clone()).into_ptr(),
None => std::ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_tool_calls_push(
handle: *mut BlazenChatMessage,
tool_call: *mut BlazenToolCall,
) {
if tool_call.is_null() {
return;
}
let tc_box = unsafe { Box::from_raw(tool_call) };
if handle.is_null() {
drop(tc_box);
return;
}
let m = unsafe { &mut *handle };
m.0.tool_calls.push(tc_box.0);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_tool_calls_count(
handle: *const BlazenChatMessage,
) -> usize {
if handle.is_null() {
return 0;
}
let m = unsafe { &*handle };
m.0.tool_calls.len()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_tool_calls_get(
handle: *const BlazenChatMessage,
idx: usize,
) -> *mut BlazenToolCall {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
match m.0.tool_calls.get(idx) {
Some(tc) => BlazenToolCall(tc.clone()).into_ptr(),
None => std::ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_set_tool_call_id(
handle: *mut BlazenChatMessage,
value: *const c_char,
) {
if handle.is_null() {
return;
}
let m = unsafe { &mut *handle };
m.0.tool_call_id = unsafe { cstr_to_opt_string(value) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_tool_call_id(
handle: *const BlazenChatMessage,
) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
match &m.0.tool_call_id {
Some(s) => alloc_cstring(s),
None => std::ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_set_name(
handle: *mut BlazenChatMessage,
value: *const c_char,
) {
if handle.is_null() {
return;
}
let m = unsafe { &mut *handle };
m.0.name = unsafe { cstr_to_opt_string(value) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_name(handle: *const BlazenChatMessage) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let m = unsafe { &*handle };
match &m.0.name {
Some(s) => alloc_cstring(s),
None => std::ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_chat_message_free(handle: *mut BlazenChatMessage) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
pub struct BlazenCompletionRequest(pub(crate) InnerCompletionRequest);
impl BlazenCompletionRequest {
pub(crate) fn into_ptr(self) -> *mut BlazenCompletionRequest {
Box::into_raw(Box::new(self))
}
}
impl From<InnerCompletionRequest> for BlazenCompletionRequest {
fn from(inner: InnerCompletionRequest) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub extern "C" fn blazen_completion_request_new() -> *mut BlazenCompletionRequest {
BlazenCompletionRequest(InnerCompletionRequest {
messages: Vec::new(),
tools: Vec::new(),
temperature: None,
max_tokens: None,
top_p: None,
model: None,
response_format_json: None,
system: None,
})
.into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_messages_push(
handle: *mut BlazenCompletionRequest,
message: *mut BlazenChatMessage,
) {
if message.is_null() {
return;
}
let msg_box = unsafe { Box::from_raw(message) };
if handle.is_null() {
drop(msg_box);
return;
}
let r = unsafe { &mut *handle };
r.0.messages.push(msg_box.0);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_tools_push(
handle: *mut BlazenCompletionRequest,
tool: *mut BlazenTool,
) {
if tool.is_null() {
return;
}
let tool_box = unsafe { Box::from_raw(tool) };
if handle.is_null() {
drop(tool_box);
return;
}
let r = unsafe { &mut *handle };
r.0.tools.push(tool_box.0);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_set_temperature(
handle: *mut BlazenCompletionRequest,
value: f64,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.temperature = Some(value);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_clear_temperature(
handle: *mut BlazenCompletionRequest,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.temperature = None;
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_set_max_tokens(
handle: *mut BlazenCompletionRequest,
value: u32,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.max_tokens = Some(value);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_clear_max_tokens(
handle: *mut BlazenCompletionRequest,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.max_tokens = None;
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_set_top_p(
handle: *mut BlazenCompletionRequest,
value: f64,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.top_p = Some(value);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_clear_top_p(
handle: *mut BlazenCompletionRequest,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.top_p = None;
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_set_model(
handle: *mut BlazenCompletionRequest,
value: *const c_char,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.model = unsafe { cstr_to_opt_string(value) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_set_response_format_json(
handle: *mut BlazenCompletionRequest,
value: *const c_char,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.response_format_json = unsafe { cstr_to_opt_string(value) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_set_system(
handle: *mut BlazenCompletionRequest,
value: *const c_char,
) {
if handle.is_null() {
return;
}
let r = unsafe { &mut *handle };
r.0.system = unsafe { cstr_to_opt_string(value) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_request_free(handle: *mut BlazenCompletionRequest) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
pub struct BlazenCompletionResponse(pub(crate) InnerCompletionResponse);
impl BlazenCompletionResponse {
pub(crate) fn into_ptr(self) -> *mut BlazenCompletionResponse {
Box::into_raw(Box::new(self))
}
}
impl From<InnerCompletionResponse> for BlazenCompletionResponse {
fn from(inner: InnerCompletionResponse) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_content(
handle: *const BlazenCompletionResponse,
) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let r = unsafe { &*handle };
alloc_cstring(&r.0.content)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_finish_reason(
handle: *const BlazenCompletionResponse,
) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let r = unsafe { &*handle };
alloc_cstring(&r.0.finish_reason)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_model(
handle: *const BlazenCompletionResponse,
) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let r = unsafe { &*handle };
alloc_cstring(&r.0.model)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_tool_calls_count(
handle: *const BlazenCompletionResponse,
) -> usize {
if handle.is_null() {
return 0;
}
let r = unsafe { &*handle };
r.0.tool_calls.len()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_tool_calls_get(
handle: *const BlazenCompletionResponse,
idx: usize,
) -> *mut BlazenToolCall {
if handle.is_null() {
return std::ptr::null_mut();
}
let r = unsafe { &*handle };
match r.0.tool_calls.get(idx) {
Some(tc) => BlazenToolCall(tc.clone()).into_ptr(),
None => std::ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_usage(
handle: *const BlazenCompletionResponse,
) -> *mut BlazenTokenUsage {
if handle.is_null() {
return std::ptr::null_mut();
}
let r = unsafe { &*handle };
BlazenTokenUsage(r.0.usage.clone()).into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_free(handle: *mut BlazenCompletionResponse) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
pub struct BlazenEmbeddingResponse(pub(crate) InnerEmbeddingResponse);
impl BlazenEmbeddingResponse {
pub(crate) fn into_ptr(self) -> *mut BlazenEmbeddingResponse {
Box::into_raw(Box::new(self))
}
}
impl From<InnerEmbeddingResponse> for BlazenEmbeddingResponse {
fn from(inner: InnerEmbeddingResponse) -> Self {
Self(inner)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_embeddings_count(
handle: *const BlazenEmbeddingResponse,
) -> usize {
if handle.is_null() {
return 0;
}
let r = unsafe { &*handle };
r.0.embeddings.len()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_embedding_dim(
handle: *const BlazenEmbeddingResponse,
vec_idx: usize,
) -> usize {
if handle.is_null() {
return 0;
}
let r = unsafe { &*handle };
r.0.embeddings.get(vec_idx).map_or(0, Vec::len)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_embedding_get(
handle: *const BlazenEmbeddingResponse,
vec_idx: usize,
dim_idx: usize,
) -> f64 {
if handle.is_null() {
return 0.0;
}
let r = unsafe { &*handle };
r.0.embeddings
.get(vec_idx)
.and_then(|v| v.get(dim_idx))
.copied()
.unwrap_or(0.0)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_embedding_to_buffer(
handle: *const BlazenEmbeddingResponse,
vec_idx: usize,
out_buf: *mut f64,
out_buf_len: usize,
) -> usize {
if handle.is_null() || out_buf.is_null() || out_buf_len == 0 {
return 0;
}
let r = unsafe { &*handle };
let Some(vec) = r.0.embeddings.get(vec_idx) else {
return 0;
};
let n = vec.len().min(out_buf_len);
unsafe {
std::ptr::copy_nonoverlapping(vec.as_ptr(), out_buf, n);
}
n
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_model(
handle: *const BlazenEmbeddingResponse,
) -> *mut c_char {
if handle.is_null() {
return std::ptr::null_mut();
}
let r = unsafe { &*handle };
alloc_cstring(&r.0.model)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_usage(
handle: *const BlazenEmbeddingResponse,
) -> *mut BlazenTokenUsage {
if handle.is_null() {
return std::ptr::null_mut();
}
let r = unsafe { &*handle };
BlazenTokenUsage(r.0.usage.clone()).into_ptr()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_free(handle: *mut BlazenEmbeddingResponse) {
if handle.is_null() {
return;
}
drop(unsafe { Box::from_raw(handle) });
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_completion_response_from_json(
json: *const c_char,
out_err: *mut *mut BlazenError,
) -> *mut BlazenCompletionResponse {
let Some(s) =
(unsafe { read_json_input(json, "blazen_completion_response_from_json", out_err) })
else {
return std::ptr::null_mut();
};
match serde_json::from_str::<CoreCompletionResponse>(s) {
Ok(core) => BlazenCompletionResponse(InnerCompletionResponse::from(core)).into_ptr(),
Err(e) => {
write_internal_err(
out_err,
format!("blazen_completion_response_from_json: deserialize failed: {e}"),
);
std::ptr::null_mut()
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn blazen_embedding_response_from_json(
json: *const c_char,
out_err: *mut *mut BlazenError,
) -> *mut BlazenEmbeddingResponse {
let Some(s) =
(unsafe { read_json_input(json, "blazen_embedding_response_from_json", out_err) })
else {
return std::ptr::null_mut();
};
match serde_json::from_str::<CoreEmbeddingResponse>(s) {
Ok(core) => BlazenEmbeddingResponse(InnerEmbeddingResponse::from(core)).into_ptr(),
Err(e) => {
write_internal_err(
out_err,
format!("blazen_embedding_response_from_json: deserialize failed: {e}"),
);
std::ptr::null_mut()
}
}
}