mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-05-23 10:29:29 +00:00
Use safer_ffi for all functions
This commit is contained in:
parent
135347cdd0
commit
06fe6bd2d3
@ -1,6 +1,16 @@
|
|||||||
use safer_ffi::prelude::*;
|
use safer_ffi::prelude::*;
|
||||||
|
|
||||||
// Must only contain negative values, values cannot be changed once set.
|
// Must only contain negative values, values cannot be changed once set.
|
||||||
|
use safer_ffi::{
|
||||||
|
String, derive_ReprC, ffi_export,
|
||||||
|
prelude::{c_slice, repr_c},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
context::{Context, Introduction},
|
||||||
|
errors::ChatError,
|
||||||
|
types::ContentData,
|
||||||
|
};
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum ErrorCode {
|
pub enum ErrorCode {
|
||||||
None = 0,
|
None = 0,
|
||||||
@ -13,6 +23,9 @@ pub enum ErrorCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use crate::context::{Context, Introduction};
|
use crate::context::{Context, Introduction};
|
||||||
|
pub fn is_ok(error: i32) -> bool {
|
||||||
|
error == ErrorCode::None as i32
|
||||||
|
}
|
||||||
|
|
||||||
/// Opaque wrapper for Context
|
/// Opaque wrapper for Context
|
||||||
#[derive_ReprC]
|
#[derive_ReprC]
|
||||||
@ -45,18 +58,17 @@ pub fn destroy_context(ctx: repr_c::Box<ContextHandle>) {
|
|||||||
/// Returns the number of bytes written to bundle_out
|
/// Returns the number of bytes written to bundle_out
|
||||||
/// Check error_code field: 0 means success, negative values indicate errors (see ErrorCode).
|
/// Check error_code field: 0 means success, negative values indicate errors (see ErrorCode).
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
pub fn create_intro_bundle(ctx: &mut ContextHandle, mut bundle_out: c_slice::Mut<'_, u8>) -> i32 {
|
pub fn create_intro_bundle(ctx: &mut ContextHandle) -> CreateIntroResult {
|
||||||
let Ok(bundle) = ctx.0.create_intro_bundle() else {
|
match ctx.0.create_intro_bundle() {
|
||||||
return ErrorCode::UnknownError as i32;
|
Ok(v) => CreateIntroResult {
|
||||||
};
|
error_code: ErrorCode::None as i32,
|
||||||
|
intro_bytes: v.into(),
|
||||||
// Check buffer is large enough
|
},
|
||||||
if bundle_out.len() < bundle.len() {
|
Err(_e) => CreateIntroResult {
|
||||||
return ErrorCode::BufferExceeded as i32;
|
error_code: ErrorCode::UnknownError as i32,
|
||||||
|
intro_bytes: repr_c::Vec::EMPTY,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle_out[..bundle.len()].copy_from_slice(&bundle);
|
|
||||||
bundle.len() as i32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new private conversation
|
/// Creates a new private conversation
|
||||||
@ -108,11 +120,11 @@ pub fn send_content(
|
|||||||
ctx: &mut ContextHandle,
|
ctx: &mut ContextHandle,
|
||||||
convo_id: repr_c::String,
|
convo_id: repr_c::String,
|
||||||
content: c_slice::Ref<'_, u8>,
|
content: c_slice::Ref<'_, u8>,
|
||||||
) -> PayloadResult {
|
) -> SendContentResult {
|
||||||
let payloads = match ctx.0.send_content(&convo_id, &content) {
|
let payloads = match ctx.0.send_content(&convo_id, &content) {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return PayloadResult {
|
return SendContentResult {
|
||||||
error_code: ErrorCode::UnknownError as i32,
|
error_code: ErrorCode::UnknownError as i32,
|
||||||
payloads: safer_ffi::Vec::EMPTY,
|
payloads: safer_ffi::Vec::EMPTY,
|
||||||
};
|
};
|
||||||
@ -127,7 +139,7 @@ pub fn send_content(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
PayloadResult {
|
SendContentResult {
|
||||||
error_code: 0,
|
error_code: 0,
|
||||||
payloads: ffi_payloads.into(),
|
payloads: ffi_payloads.into(),
|
||||||
}
|
}
|
||||||
@ -143,35 +155,31 @@ pub fn send_content(
|
|||||||
pub fn handle_payload(
|
pub fn handle_payload(
|
||||||
ctx: &mut ContextHandle,
|
ctx: &mut ContextHandle,
|
||||||
payload: c_slice::Ref<'_, u8>,
|
payload: c_slice::Ref<'_, u8>,
|
||||||
mut conversation_id_out: c_slice::Mut<'_, u8>,
|
) -> HandlePayloadResult {
|
||||||
conversation_id_out_len: Out<'_, u32>,
|
|
||||||
mut content_out: c_slice::Mut<'_, u8>,
|
|
||||||
) -> i32 {
|
|
||||||
match ctx.0.handle_payload(&payload) {
|
match ctx.0.handle_payload(&payload) {
|
||||||
Ok(Some(content)) => {
|
Ok(o) => o.into(),
|
||||||
let convo_id_bytes = content.conversation_id.as_bytes();
|
Err(e) => e.into(),
|
||||||
|
|
||||||
if conversation_id_out.len() < convo_id_bytes.len() {
|
|
||||||
return ErrorCode::BufferExceeded as i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if content_out.len() < content.data.len() {
|
|
||||||
return ErrorCode::BufferExceeded as i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
conversation_id_out[..convo_id_bytes.len()].copy_from_slice(convo_id_bytes);
|
|
||||||
conversation_id_out_len.write(convo_id_bytes.len() as u32);
|
|
||||||
content_out[..content.data.len()].copy_from_slice(&content.data);
|
|
||||||
|
|
||||||
content.data.len() as i32
|
|
||||||
}
|
|
||||||
_ => 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Result structure for create_intro_bundle
|
||||||
|
/// error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
|
#[derive_ReprC]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CreateIntroResult {
|
||||||
|
pub error_code: i32,
|
||||||
|
pub intro_bytes: repr_c::Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// safer_ffi implementation
|
// safer_ffi implementation
|
||||||
// ===============================================================================================================================
|
// ===============================================================================================================================
|
||||||
|
/// Free the result from create_intro_bundle
|
||||||
|
#[ffi_export]
|
||||||
|
pub fn destroy_intro_result(result: CreateIntroResult) {
|
||||||
|
drop(result);
|
||||||
|
}
|
||||||
|
|
||||||
/// Payload structure for FFI
|
/// Payload structure for FFI
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -186,18 +194,71 @@ pub struct Payload {
|
|||||||
/// error_code is 0 on success, negative on error (see ErrorCode)
|
/// error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
#[derive_ReprC]
|
#[derive_ReprC]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct PayloadResult {
|
pub struct SendContentResult {
|
||||||
pub error_code: i32,
|
pub error_code: i32,
|
||||||
pub payloads: repr_c::Vec<Payload>,
|
pub payloads: repr_c::Vec<Payload>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Free the result from create_intro_bundle_safe
|
/// Free the result from create_intro_bundle_safe
|
||||||
|
/// Free the result from send_content
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
pub fn destroy_payload_result(result: PayloadResult) {
|
pub fn destroy_send_content_result(result: SendContentResult) {
|
||||||
|
drop(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Result structure for handle_payload
|
||||||
|
/// error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[derive_ReprC]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct HandlePayloadResult {
|
||||||
|
pub error_code: i32,
|
||||||
|
pub convo_id: repr_c::String,
|
||||||
|
pub content: repr_c::Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Free the result from handle_payload
|
||||||
|
#[ffi_export]
|
||||||
|
pub fn destroy_handle_payload_result(result: HandlePayloadResult) {
|
||||||
drop(result);
|
drop(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result structure for create_new_private_convo_safe
|
/// Result structure for create_new_private_convo_safe
|
||||||
|
impl From<ContentData> for HandlePayloadResult {
|
||||||
|
fn from(value: ContentData) -> Self {
|
||||||
|
HandlePayloadResult {
|
||||||
|
error_code: ErrorCode::None as i32,
|
||||||
|
convo_id: value.conversation_id.into(),
|
||||||
|
content: value.data.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<ContentData>> for HandlePayloadResult {
|
||||||
|
fn from(value: Option<ContentData>) -> Self {
|
||||||
|
if let Some(content) = value {
|
||||||
|
content.into()
|
||||||
|
} else {
|
||||||
|
HandlePayloadResult {
|
||||||
|
error_code: ErrorCode::None as i32,
|
||||||
|
convo_id: repr_c::String::EMPTY,
|
||||||
|
content: repr_c::Vec::EMPTY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ChatError> for HandlePayloadResult {
|
||||||
|
fn from(_value: ChatError) -> Self {
|
||||||
|
HandlePayloadResult {
|
||||||
|
// TODO: (P2) Translate ChatError into ErrorCode
|
||||||
|
error_code: ErrorCode::UnknownError as i32,
|
||||||
|
convo_id: String::EMPTY,
|
||||||
|
content: repr_c::Vec::EMPTY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// error_code is 0 on success, negative on error (see ErrorCode)
|
/// error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
#[derive_ReprC]
|
#[derive_ReprC]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user