1 # A handful of classes and functions to support the generated data structures.
2 # This would be a good candidate for isolating in its own ffi-support lib.
4 class InternalError(Exception):
7 class _UniffiRustCallStatus(ctypes
.Structure
):
12 ("code", ctypes
.c_int8
),
13 ("error_buf", _UniffiRustBuffer
),
16 # These match the values from the uniffi::rustcalls module
22 if self
.code
== _UniffiRustCallStatus
.CALL_SUCCESS
:
23 return "_UniffiRustCallStatus(CALL_SUCCESS)"
24 elif self
.code
== _UniffiRustCallStatus
.CALL_ERROR
:
25 return "_UniffiRustCallStatus(CALL_ERROR)"
26 elif self
.code
== _UniffiRustCallStatus
.CALL_PANIC
:
27 return "_UniffiRustCallStatus(CALL_PANIC)"
29 return "_UniffiRustCallStatus(<invalid code>)"
31 def _rust_call(fn
, *args
):
32 # Call a rust function
33 return _rust_call_with_error(None, fn
, *args
)
35 def _rust_call_with_error(error_ffi_converter
, fn
, *args
):
36 # Call a rust function and handle any errors
38 # This function is used for rust calls that return Result<> and therefore can set the CALL_ERROR status code.
39 # error_ffi_converter must be set to the _UniffiConverter for the error class that corresponds to the result.
40 call_status
= _UniffiRustCallStatus(code
=_UniffiRustCallStatus
.CALL_SUCCESS
, error_buf
=_UniffiRustBuffer(0, 0, None))
42 args_with_error
= args
+ (ctypes
.byref(call_status
),)
43 result
= fn(*args_with_error
)
44 _uniffi_check_call_status(error_ffi_converter
, call_status
)
47 def _uniffi_check_call_status(error_ffi_converter
, call_status
):
48 if call_status
.code
== _UniffiRustCallStatus
.CALL_SUCCESS
:
50 elif call_status
.code
== _UniffiRustCallStatus
.CALL_ERROR
:
51 if error_ffi_converter
is None:
52 call_status
.error_buf
.free()
53 raise InternalError("_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None")
55 raise error_ffi_converter
.lift(call_status
.error_buf
)
56 elif call_status
.code
== _UniffiRustCallStatus
.CALL_PANIC
:
57 # When the rust code sees a panic, it tries to construct a _UniffiRustBuffer
58 # with the message. But if that code panics, then it just sends back
60 if call_status
.error_buf
.len > 0:
61 msg
= _UniffiConverterString
.lift(call_status
.error_buf
)
63 msg
= "Unknown rust panic"
64 raise InternalError(msg
)
66 raise InternalError("Invalid _UniffiRustCallStatus code: {}".format(
69 # A function pointer for a callback as defined by UniFFI.
70 # Rust definition `fn(handle: u64, method: u32, args: _UniffiRustBuffer, buf_ptr: *mut _UniffiRustBuffer) -> int`
71 _UNIFFI_FOREIGN_CALLBACK_T
= ctypes
.CFUNCTYPE(ctypes
.c_int
, ctypes
.c_ulonglong
, ctypes
.c_ulong
, ctypes
.POINTER(ctypes
.c_char
), ctypes
.c_int
, ctypes
.POINTER(_UniffiRustBuffer
))
73 # UniFFI future continuation
74 _UNIFFI_FUTURE_CONTINUATION_T
= ctypes
.CFUNCTYPE(None, ctypes
.c_size_t
, ctypes
.c_int8
)