mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-02-17 20:23:33 +00:00
Update nim bindings
This commit is contained in:
parent
98c74a120e
commit
9aad91a054
@ -68,10 +68,23 @@ type
|
|||||||
|
|
||||||
## Result structure for create_intro_bundle
|
## Result structure for create_intro_bundle
|
||||||
## error_code is 0 on success, negative on error (see ErrorCode)
|
## error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
PayloadResult* = object
|
CreateIntroResult* = object
|
||||||
|
error_code*: int32
|
||||||
|
intro_bytes*: VecUint8
|
||||||
|
|
||||||
|
## Result structure for send_content
|
||||||
|
## error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
|
SendContentResult* = object
|
||||||
error_code*: int32
|
error_code*: int32
|
||||||
payloads*: VecPayload
|
payloads*: VecPayload
|
||||||
|
|
||||||
|
## Result structure for handle_payload
|
||||||
|
## error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
|
HandlePayloadResult* = object
|
||||||
|
error_code*: int32
|
||||||
|
convo_id*: ReprCString
|
||||||
|
content*: VecUint8
|
||||||
|
|
||||||
## Result from create_new_private_convo
|
## Result from create_new_private_convo
|
||||||
## error_code is 0 on success, negative on error (see ErrorCode)
|
## error_code is 0 on success, negative on error (see ErrorCode)
|
||||||
NewConvoResult* = object
|
NewConvoResult* = object
|
||||||
@ -91,11 +104,11 @@ proc create_context*(): ContextHandle {.importc, dynlib: CONVERSATIONS_LIB.}
|
|||||||
proc destroy_context*(ctx: ContextHandle) {.importc, dynlib: CONVERSATIONS_LIB.}
|
proc destroy_context*(ctx: ContextHandle) {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
|
|
||||||
## Creates an intro bundle for sharing with other users
|
## Creates an intro bundle for sharing with other users
|
||||||
## Returns: Number of bytes written to bundle_out, or negative error code
|
## Returns: CreateIntroResult struct - check error_code field (0 = success, negative = error)
|
||||||
|
## The result must be freed with destroy_intro_result()
|
||||||
proc create_intro_bundle*(
|
proc create_intro_bundle*(
|
||||||
ctx: ContextHandle,
|
ctx: ContextHandle,
|
||||||
bundle_out: SliceUint8,
|
): CreateIntroResult {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
): int32 {.importc, dynlib: CONVERSATIONS_LIB.}
|
|
||||||
|
|
||||||
## Creates a new private conversation
|
## Creates a new private conversation
|
||||||
## Returns: NewConvoResult struct - check error_code field (0 = success, negative = error)
|
## Returns: NewConvoResult struct - check error_code field (0 = success, negative = error)
|
||||||
@ -107,30 +120,35 @@ proc create_new_private_convo*(
|
|||||||
): NewConvoResult {.importc, dynlib: CONVERSATIONS_LIB.}
|
): NewConvoResult {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
|
|
||||||
## Sends content to an existing conversation
|
## Sends content to an existing conversation
|
||||||
## Returns: PayloadResult struct - check error_code field (0 = success, negative = error)
|
## Returns: SendContentResult struct - check error_code field (0 = success, negative = error)
|
||||||
## The result must be freed with destroy_payload_result()
|
## The result must be freed with destroy_send_content_result()
|
||||||
proc send_content*(
|
proc send_content*(
|
||||||
ctx: ContextHandle,
|
ctx: ContextHandle,
|
||||||
convo_id: SliceUint8,
|
convo_id: ReprCString,
|
||||||
content: SliceUint8,
|
content: SliceUint8,
|
||||||
): PayloadResult {.importc, dynlib: CONVERSATIONS_LIB.}
|
): SendContentResult {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
|
|
||||||
## Handles an incoming payload and writes content to caller-provided buffers
|
## Handles an incoming payload
|
||||||
## Returns: Number of bytes written to content_out on success (>= 0), negative error code on failure
|
## Returns: HandlePayloadResult struct - check error_code field (0 = success, negative = error)
|
||||||
## conversation_id_out_len is set to the number of bytes written to conversation_id_out
|
## This call does not always generate content. If content is zero bytes long then there
|
||||||
|
## is no data, and the convo_id should be ignored.
|
||||||
|
## The result must be freed with destroy_handle_payload_result()
|
||||||
proc handle_payload*(
|
proc handle_payload*(
|
||||||
ctx: ContextHandle,
|
ctx: ContextHandle,
|
||||||
payload: SliceUint8,
|
payload: SliceUint8,
|
||||||
conversation_id_out: SliceUint8,
|
): HandlePayloadResult {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
conversation_id_out_len: ptr uint32,
|
|
||||||
content_out: SliceUint8,
|
## Free the result from create_intro_bundle
|
||||||
): int32 {.importc, dynlib: CONVERSATIONS_LIB.}
|
proc destroy_intro_result*(result: CreateIntroResult) {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
|
|
||||||
## Free the result from create_new_private_convo
|
## Free the result from create_new_private_convo
|
||||||
proc destroy_convo_result*(result: NewConvoResult) {.importc, dynlib: CONVERSATIONS_LIB.}
|
proc destroy_convo_result*(result: NewConvoResult) {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
|
|
||||||
## Free the PayloadResult
|
## Free the result from send_content
|
||||||
proc destroy_payload_result*(result: PayloadResult) {.importc, dynlib: CONVERSATIONS_LIB.}
|
proc destroy_send_content_result*(result: SendContentResult) {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
|
|
||||||
|
## Free the result from handle_payload
|
||||||
|
proc destroy_handle_payload_result*(result: HandlePayloadResult) {.importc, dynlib: CONVERSATIONS_LIB.}
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Helper functions
|
# Helper functions
|
||||||
@ -157,6 +175,16 @@ proc `$`*(s: ReprCString): string =
|
|||||||
result = newString(s.len)
|
result = newString(s.len)
|
||||||
copyMem(addr result[0], s.ptr, s.len)
|
copyMem(addr result[0], s.ptr, s.len)
|
||||||
|
|
||||||
|
## Create a ReprCString from a Nim string for passing to FFI functions.
|
||||||
|
## WARNING: The returned ReprCString borrows from the input string.
|
||||||
|
## The input string must remain valid for the duration of the FFI call.
|
||||||
|
## cap is set to 0 to prevent Rust from attempting to deallocate Nim memory.
|
||||||
|
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: 0)
|
||||||
|
|
||||||
## Convert a VecUint8 to a seq[byte]
|
## Convert a VecUint8 to a seq[byte]
|
||||||
proc toSeq*(v: VecUint8): seq[byte] =
|
proc toSeq*(v: VecUint8): seq[byte] =
|
||||||
if v.ptr == nil or v.len == 0:
|
if v.ptr == nil or v.len == 0:
|
||||||
@ -173,6 +201,11 @@ proc `[]`*(v: VecPayload, i: int): Payload =
|
|||||||
proc len*(v: VecPayload): int =
|
proc len*(v: VecPayload): int =
|
||||||
int(v.len)
|
int(v.len)
|
||||||
|
|
||||||
|
## Iterator for VecPayload
|
||||||
|
iterator items*(v: VecPayload): Payload =
|
||||||
|
for i in 0 ..< v.len:
|
||||||
|
yield v[int(i)]
|
||||||
|
|
||||||
## Convert a string to seq[byte]
|
## Convert a string to seq[byte]
|
||||||
proc toBytes*(s: string): seq[byte] =
|
proc toBytes*(s: string): seq[byte] =
|
||||||
if s.len == 0:
|
if s.len == 0:
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import std/options
|
import std/options
|
||||||
|
import std/sequtils
|
||||||
import results
|
import results
|
||||||
import bindings
|
import bindings
|
||||||
|
|
||||||
@ -31,22 +32,21 @@ proc getBuffer*(ctx: LibChat): seq[byte] =
|
|||||||
newSeq[byte](ctx.buffer_size)
|
newSeq[byte](ctx.buffer_size)
|
||||||
|
|
||||||
## Generate a Introduction Bundle
|
## Generate a Introduction Bundle
|
||||||
proc createIntroductionBundle*(ctx: LibChat): Result[string, string] =
|
proc createIntroductionBundle*(ctx: LibChat): Result[seq[byte], string] =
|
||||||
if ctx.handle == nil:
|
if ctx.handle == nil:
|
||||||
return err("Context handle is nil")
|
return err("Context handle is nil")
|
||||||
|
|
||||||
var buffer = ctx.getBuffer()
|
let res = create_intro_bundle(ctx.handle)
|
||||||
var slice = buffer.toSlice()
|
|
||||||
let len = create_intro_bundle(ctx.handle, slice)
|
|
||||||
|
|
||||||
if len < 0:
|
if res.error_code != ErrNone:
|
||||||
return err("Failed to create intro bundle: " & $len)
|
result = err("Failed to create private convo: " & $res.error_code)
|
||||||
|
destroy_intro_result(res)
|
||||||
|
return
|
||||||
|
|
||||||
buffer.setLen(len)
|
return ok(res.intro_bytes.toSeq())
|
||||||
return ok(cast[string](buffer))
|
|
||||||
|
|
||||||
## Create a Private Convo
|
## Create a Private Convo
|
||||||
proc createNewPrivateConvo*(ctx: LibChat, bundle: string, content: seq[byte]): Result[(string, seq[PayloadResult]), string] =
|
proc createNewPrivateConvo*(ctx: LibChat, bundle: seq[byte], content: seq[byte]): Result[(string, seq[PayloadResult]), string] =
|
||||||
if ctx.handle == nil:
|
if ctx.handle == nil:
|
||||||
return err("Context handle is nil")
|
return err("Context handle is nil")
|
||||||
|
|
||||||
@ -92,25 +92,22 @@ proc sendContent*(ctx: LibChat, convoId: string, content: seq[byte]): Result[seq
|
|||||||
|
|
||||||
let res = bindings.send_content(
|
let res = bindings.send_content(
|
||||||
ctx.handle,
|
ctx.handle,
|
||||||
convoId.toSlice(),
|
convoId.toReprCString,
|
||||||
content.toSlice()
|
content.toSlice()
|
||||||
)
|
)
|
||||||
|
|
||||||
if res.error_code != 0:
|
if res.error_code != 0:
|
||||||
result = err("Failed to send content: " & $res.error_code)
|
result = err("Failed to send content: " & $res.error_code)
|
||||||
destroy_payload_result(res)
|
destroy_send_content_result(res)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Convert payloads to Nim types
|
|
||||||
var payloads = newSeq[PayloadResult](res.payloads.len)
|
|
||||||
for i in 0 ..< res.payloads.len:
|
|
||||||
let p = res.payloads[int(i)]
|
|
||||||
payloads[int(i)] = PayloadResult(
|
|
||||||
address: $p.address,
|
|
||||||
data: p.data.toSeq()
|
|
||||||
)
|
|
||||||
|
|
||||||
destroy_payload_result(res)
|
let payloads = res.payloads.toSeq().mapIt(PayloadResult(
|
||||||
|
address: $it.address,
|
||||||
|
data: it.data.toSeq()
|
||||||
|
))
|
||||||
|
|
||||||
|
destroy_send_content_result(res)
|
||||||
return ok(payloads)
|
return ok(payloads)
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -130,26 +127,21 @@ proc handlePayload*(ctx: LibChat, payload: seq[byte]): Result[Option[ContentResu
|
|||||||
var contentBuf = newSeq[byte](ctx.buffer_size)
|
var contentBuf = newSeq[byte](ctx.buffer_size)
|
||||||
var conversationIdLen: uint32 = 0
|
var conversationIdLen: uint32 = 0
|
||||||
|
|
||||||
let bytesWritten = bindings.handle_payload(
|
let res = bindings.handle_payload(
|
||||||
ctx.handle,
|
ctx.handle,
|
||||||
payload.toSlice(),
|
payload.toSlice(),
|
||||||
conversationIdBuf.toSlice(),
|
|
||||||
addr conversationIdLen,
|
|
||||||
contentBuf.toSlice()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if bytesWritten < 0:
|
if res.error_code != ErrNone:
|
||||||
return err("Failed to handle payload: " & $bytesWritten)
|
return err("Failed to handle payload: " & $res.error_code)
|
||||||
|
|
||||||
if bytesWritten == 0:
|
let content = res.content.toSeq()
|
||||||
|
if content.len == 0:
|
||||||
return ok(none(ContentResult))
|
return ok(none(ContentResult))
|
||||||
|
|
||||||
conversationIdBuf.setLen(conversationIdLen)
|
|
||||||
contentBuf.setLen(bytesWritten)
|
|
||||||
|
|
||||||
return ok(some(ContentResult(
|
return ok(some(ContentResult(
|
||||||
conversationId: cast[string](conversationIdBuf),
|
conversationId: $res.convo_id,
|
||||||
data: contentBuf
|
data: content
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user