Update bindings to include types

This commit is contained in:
Jazz Turner-Baggs 2026-02-04 10:18:32 -08:00
parent 4dd40eeff7
commit 3b90c9d58a
No known key found for this signature in database
3 changed files with 67 additions and 39 deletions

View File

@ -12,7 +12,10 @@ pub enum ErrorCode {
UnknownError = -6,
}
use crate::context::{Context, Introduction};
use crate::{
context::{Context, Introduction},
types::ContentData,
};
/// Opaque wrapper for Context
#[derive_ReprC]
@ -156,7 +159,8 @@ pub fn handle_payload(
HandlePayloadResult {
error_code: ErrorCode::NotImplemented as i32,
convo_id: "".into(),
payloads: safer_ffi::Vec::EMPTY,
content: safer_ffi::Vec::EMPTY,
events: Events::None,
}
}
@ -188,6 +192,12 @@ pub fn destroy_send_content_result(result: SendContentResult) {
drop(result);
}
#[derive_ReprC]
#[repr(i32)]
pub enum Events {
None = 0,
NewConvo = 1,
}
/// Result structure for create_new_private_convo_safe
/// error_code is 0 on success, negative on error (see ErrorCode)
#[derive_ReprC]
@ -195,7 +205,8 @@ pub fn destroy_send_content_result(result: SendContentResult) {
pub struct HandlePayloadResult {
pub error_code: i32,
pub convo_id: repr_c::String,
pub payloads: repr_c::Vec<Payload>,
pub content: repr_c::Vec<u8>,
pub events: Events,
}
/// Free the result from create_new_private_convo_safe

View File

@ -66,12 +66,25 @@ type
len*: csize_t
cap*: csize_t
## Result structure for create_intro_bundle
## Events enum for handle_payload
Events* = enum
evNone = 0
evNewConvo = 1
## Result structure for send_content
## error_code is 0 on success, negative on error (see ErrorCode)
PayloadResult* = object
SendContentResult* = object
error_code*: int32
payloads*: VecPayload
## Result from handle_payload
## error_code is 0 on success, negative on error (see ErrorCode)
HandlePayloadResult* = object
error_code*: int32
convo_id*: ReprCString
content*: VecUint8
events*: Events
## Result from create_new_private_convo
## error_code is 0 on success, negative on error (see ErrorCode)
NewConvoResult* = object
@ -107,30 +120,30 @@ proc create_new_private_convo*(
): NewConvoResult {.importc, dynlib: CONVERSATIONS_LIB.}
## Sends content to an existing conversation
## Returns: PayloadResult struct - check error_code field (0 = success, negative = error)
## The result must be freed with destroy_payload_result()
## Returns: SendContentResult struct - check error_code field (0 = success, negative = error)
## The result must be freed with destroy_send_content_result()
proc send_content*(
ctx: ContextHandle,
convo_id: SliceUint8,
convo_id: ReprCString,
content: SliceUint8,
): PayloadResult {.importc, dynlib: CONVERSATIONS_LIB.}
): SendContentResult {.importc, dynlib: CONVERSATIONS_LIB.}
## Handles an incoming payload and writes content to caller-provided buffers
## Returns: Number of bytes written to content_out on success (>= 0), negative error code on failure
## conversation_id_out_len is set to the number of bytes written to conversation_id_out
## Handles an incoming payload
## Returns: HandlePayloadResult struct - check error_code field (0 = success, negative = error)
## The result must be freed with destroy_handle_payload_result()
proc handle_payload*(
ctx: ContextHandle,
payload: SliceUint8,
conversation_id_out: SliceUint8,
conversation_id_out_len: ptr uint32,
content_out: SliceUint8,
): int32 {.importc, dynlib: CONVERSATIONS_LIB.}
): HandlePayloadResult {.importc, dynlib: CONVERSATIONS_LIB.}
## Free the result from create_new_private_convo
proc destroy_convo_result*(result: NewConvoResult) {.importc, dynlib: CONVERSATIONS_LIB.}
## Free the PayloadResult
proc destroy_payload_result*(result: PayloadResult) {.importc, dynlib: CONVERSATIONS_LIB.}
## Free the SendContentResult
proc destroy_send_content_result*(result: SendContentResult) {.importc, dynlib: CONVERSATIONS_LIB.}
## Free the HandlePayloadResult
proc destroy_handle_payload_result*(result: HandlePayloadResult) {.importc, dynlib: CONVERSATIONS_LIB.}
# ============================================================================
# Helper functions
@ -157,6 +170,13 @@ proc `$`*(s: ReprCString): string =
result = newString(s.len)
copyMem(addr result[0], s.ptr, s.len)
## Create a ReprCString from a Nim string (borrows memory - string must outlive usage)
proc toReprCString*(s: string): ReprCString =
if s.len == 0:
ReprCString(`ptr`: nil, len: 0, cap: 0)
else:
ReprCString(`ptr`: cast[ptr char](unsafeAddr s[0]), len: csize_t(s.len), cap: csize_t(s.len))
## Convert a VecUint8 to a seq[byte]
proc toSeq*(v: VecUint8): seq[byte] =
if v.ptr == nil or v.len == 0:

View File

@ -92,13 +92,13 @@ proc sendContent*(ctx: LibChat, convoId: string, content: seq[byte]): Result[seq
let res = bindings.send_content(
ctx.handle,
convoId.toSlice(),
convoId.toReprCString(),
content.toSlice()
)
if res.error_code != 0:
result = err("Failed to send content: " & $res.error_code)
destroy_payload_result(res)
destroy_send_content_result(res)
return
# Convert payloads to Nim types
@ -110,7 +110,7 @@ proc sendContent*(ctx: LibChat, convoId: string, content: seq[byte]): Result[seq
data: p.data.toSeq()
)
destroy_payload_result(res)
destroy_send_content_result(res)
return ok(payloads)
type
@ -126,31 +126,28 @@ proc handlePayload*(ctx: LibChat, payload: seq[byte]): Result[Option[ContentResu
if payload.len == 0:
return err("payload is zero length")
var conversationIdBuf = newSeq[byte](ctx.buffer_size)
var contentBuf = newSeq[byte](ctx.buffer_size)
var conversationIdLen: uint32 = 0
let bytesWritten = bindings.handle_payload(
let res = bindings.handle_payload(
ctx.handle,
payload.toSlice(),
conversationIdBuf.toSlice(),
addr conversationIdLen,
contentBuf.toSlice()
payload.toSlice()
)
if bytesWritten < 0:
return err("Failed to handle payload: " & $bytesWritten)
if res.error_code != 0:
result = err("Failed to handle payload: " & $res.error_code)
destroy_handle_payload_result(res)
return
if bytesWritten == 0:
# Check if there's content
if res.content.len == 0:
destroy_handle_payload_result(res)
return ok(none(ContentResult))
conversationIdBuf.setLen(conversationIdLen)
contentBuf.setLen(bytesWritten)
let content = ContentResult(
conversationId: $res.convo_id,
data: res.content.toSeq()
)
return ok(some(ContentResult(
conversationId: cast[string](conversationIdBuf),
data: contentBuf
)))
destroy_handle_payload_result(res)
return ok(some(content))
proc `=destroy`(x: var LibChat) =