7#ifndef BOTAN_FFI_UTILS_H_
8#define BOTAN_FFI_UTILS_H_
10#include <botan/exceptn.h>
12#include <botan/mem_ops.h>
22 FFI_Error(std::string_view what,
int err_code) : Exception(
"FFI error", what), m_err_code(err_code) {}
24 int error_code() const noexcept
override {
return m_err_code; }
32template <
typename T, u
int32_t MAGIC>
35 botan_struct(std::unique_ptr<T> obj) : m_magic(MAGIC), m_obj(std::move(obj)) {}
42 bool magic_ok()
const {
return (m_magic == MAGIC); }
48 std::unique_ptr<T> m_obj;
51#define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC) \
52 struct NAME final : public Botan_FFI::botan_struct<TYPE, MAGIC> { \
53 explicit NAME(std::unique_ptr<TYPE> x) : botan_struct(std::move(x)) {} \
56#define BOTAN_FFI_DECLARE_DUMMY_STRUCT(NAME, MAGIC) \
57 struct NAME final : public Botan_FFI::botan_struct<int, MAGIC> {}
62template <
typename T, u
int32_t M>
78int ffi_guard_thunk(
const char* func_name,
const std::function<
int()>& thunk);
80template <
typename T, u
int32_t M,
typename F>
82 using RetT = std::invoke_result_t<F, T&>;
83 static_assert(std::is_void_v<RetT> || std::is_same_v<RetT, BOTAN_FFI_ERROR> || std::is_same_v<RetT, int>,
84 "BOTAN_FFI_DO must be used with a block that returns either nothing, int or BOTAN_FFI_ERROR");
99 if constexpr(std::is_void_v<RetT>) {
124#define BOTAN_FFI_VISIT(obj, lambda) botan_ffi_visit(obj, lambda, __func__)
126template <
typename T, u
int32_t M>
143#define BOTAN_FFI_CHECKED_DELETE(o) ffi_delete_object(o, __func__)
145template <
typename Alloc>
147 return view(ctx, buf.data(), buf.size());
151 return view(ctx, str.data(), str.size() + 1);
162template <
typename Fn,
typename... Args>
170template <
typename Fn,
typename... Args>
181inline int write_output(uint8_t out[],
size_t* out_len,
const uint8_t buf[],
size_t buf_len) {
182 if(out_len ==
nullptr) {
186 const size_t avail = *out_len;
189 if((avail >= buf_len) && (out !=
nullptr)) {
200template <
typename Alloc>
201int write_vec_output(uint8_t out[],
size_t* out_len,
const std::vector<uint8_t, Alloc>& buf) {
202 return write_output(out, out_len, buf.data(), buf.size());
213inline int write_str_output(
char out[],
size_t* out_len,
const std::vector<uint8_t>& str_vec) {
Botan::ErrorType error_type() const noexcept override
FFI_Error(std::string_view what, int err_code)
int error_code() const noexcept override
int(* final)(unsigned char *, CTX *)
#define BOTAN_UNSTABLE_API
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_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)
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 write_str_output(uint8_t out[], size_t *out_len, std::string_view str)
int ffi_delete_object(botan_struct< T, M > *obj, const char *func_name)
T & safe_get(botan_struct< T, M > *p)
int invoke_view_callback(botan_view_bin_fn view, botan_view_ctx ctx, const std::vector< uint8_t, Alloc > &buf)
int copy_view_str(uint8_t out[], size_t *out_len, Fn fn, Args... args)
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
int write_output(uint8_t out[], size_t *out_len, const uint8_t buf[], size_t buf_len)
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr void clear_mem(T *ptr, size_t n)
const uint8_t * cast_char_ptr_to_uint8(const char *s)
botan_struct(std::unique_ptr< T > obj)