7#ifndef BOTAN_FFI_UTILS_H_
8#define BOTAN_FFI_UTILS_H_
10#include <botan/exceptn.h>
12#include <botan/mem_ops.h>
13#include <botan/internal/mem_utils.h>
27 int error_code() const noexcept
override {
return m_err_code; }
35template <
typename T, u
int32_t MAGIC>
38 explicit botan_struct(std::unique_ptr<T> obj) : m_magic(MAGIC), m_obj(std::move(obj)) {}
50 bool magic_ok()
const {
return (m_magic == MAGIC); }
56 std::unique_ptr<T> m_obj;
61#define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC) \
62 struct NAME final : public Botan_FFI::botan_struct<TYPE, MAGIC> { \
63 explicit NAME(std::unique_ptr<TYPE> x) : botan_struct(std::move(x)) {} \
66#define BOTAN_FFI_DECLARE_DUMMY_STRUCT(NAME, MAGIC) \
67 struct NAME final : public Botan_FFI::botan_struct<int, MAGIC> {}
78template <
typename T, u
int32_t M>
94template <std::invocable T>
100 }
catch(std::bad_alloc&) {
106 }
catch(std::exception& e) {
113template <
typename T, u
int32_t M,
typename F>
115 using RetT = std::invoke_result_t<F, T&>;
116 static_assert(std::is_void_v<RetT> || std::is_same_v<RetT, BOTAN_FFI_ERROR> || std::is_same_v<RetT, int>,
117 "BOTAN_FFI_DO must be used with a block that returns either nothing, int or BOTAN_FFI_ERROR");
132 if constexpr(std::is_void_v<RetT>) {
158#define BOTAN_FFI_VISIT(obj, lambda) botan_ffi_visit(obj, lambda, __func__)
160template <
typename T, u
int32_t M>
177template <
typename T,
typename... Args>
180 *obj =
new std::remove_pointer_t<T>(std::forward<Args>(args)...);
185#define BOTAN_FFI_CHECKED_DELETE(o) ffi_delete_object(o, __func__)
188 if(view ==
nullptr) {
191 return view(ctx, buf.data(), buf.size());
196 if(view ==
nullptr) {
199 return view(ctx, str.data(), str.size() + 1);
210template <
typename Fn,
typename... Args>
216template <
typename Fn,
typename... Args>
225template <std::
integral T>
226inline int write_output(T out[],
size_t* out_len,
const T buf[],
size_t buf_len) {
227 static_assert(
sizeof(T) == 1,
"T should be either uint8_t or char");
229 if(out_len ==
nullptr) {
233 const size_t avail = *out_len;
236 if((avail >= buf_len) && (out !=
nullptr)) {
#define BOTAN_UNSTABLE_API
const char * what() const noexcept override
Exception(std::string_view msg)
Botan::ErrorType error_type() const noexcept override
FFI_Error(std::string_view what, int err_code)
int error_code() const noexcept override
int(* botan_view_bin_fn)(botan_view_ctx view_ctx, const uint8_t *data, size_t len)
@ BOTAN_FFI_ERROR_EXCEPTION_THROWN
@ BOTAN_FFI_ERROR_OUT_OF_MEMORY
@ BOTAN_FFI_ERROR_INVALID_OBJECT
@ BOTAN_FFI_ERROR_NULL_POINTER
@ BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE
int(* botan_view_str_fn)(botan_view_ctx view_ctx, const char *str, size_t len)
void ffi_clear_last_exception()
int invoke_view_callback(botan_view_bin_fn view, botan_view_ctx ctx, std::span< const uint8_t > buf)
int ffi_error_exception_thrown(const char *func_name, const char *exn, int rc)
int botan_view_bin_bounce_fn(botan_view_ctx vctx, const uint8_t *buf, size_t len)
int botan_view_str_bounce_fn(botan_view_ctx vctx, const char *str, size_t len)
int botan_ffi_visit(botan_struct< T, M > *o, F func, const char *func_name)
int copy_view_bin(uint8_t out[], size_t *out_len, Fn fn, Args... args)
int ffi_delete_object(botan_struct< T, M > *obj, const char *func_name)
T & safe_get(botan_struct< T, M > *p)
BOTAN_FFI_ERROR ffi_new_object(T *obj, Args &&... args)
int copy_view_str(uint8_t out[], size_t *out_len, Fn fn, Args... args)
int write_output(T out[], size_t *out_len, const T buf[], size_t buf_len)
int ffi_guard_thunk(const char *func_name, T thunk)
int write_vec_output(uint8_t out[], size_t *out_len, std::span< const uint8_t > buf)
int write_str_output(char out[], size_t *out_len, const std::string &str)
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr void clear_mem(T *ptr, size_t n)
bool any_null_pointers(Ptrs... ptr)
botan_struct(const botan_struct &other)=delete
botan_struct(std::unique_ptr< T > obj)
botan_struct & operator=(const botan_struct &other)=delete
botan_struct(botan_struct &&other)=delete
botan_struct & operator=(botan_struct &&other)=delete