Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
msgpack_impl.hpp
Go to the documentation of this file.
1#pragma once
2// Meant to be the main header included by *.cpp files* that use msgpack.
3// Note: heavy header due to serialization logic, don't include if msgpack.hpp will do
4// CBinding helpers that take a function or a lambda and
5// - bind the input as a coded msgpack array of all the arguments (using template metamagic)
6// - bind the return value to an out buffer, where the caller must free the memory
7
8#include <cstring>
9#include <type_traits>
10
12
22
31 uint8_t* scratch_buf = nullptr,
32 size_t scratch_size = 0)
33{
34 // Create a buffer to store the encoded data
35 msgpack::sbuffer buffer;
36 msgpack::pack(buffer, obj);
37
38 // If scratch buffer provided and result fits, use it
39 if (scratch_buf != nullptr && buffer.size() <= scratch_size) {
40 memcpy(scratch_buf, buffer.data(), buffer.size());
41 return { scratch_buf, buffer.size() };
42 }
43
44 // Otherwise allocate new buffer
45 uint8_t* output = static_cast<uint8_t*>(aligned_alloc(64, buffer.size()));
46 memcpy(output, buffer.data(), buffer.size());
47 return { output, buffer.size() };
48}
49
50// This function is intended to bind a function to a MessagePack-formatted input data,
51// perform the function with the unpacked data, then pack the result back into MessagePack format.
52// Note: output_out and output_len_out are IN-OUT parameters:
53// IN: Caller provides scratch buffer pointer and size
54// OUT: Returns actual result buffer (may be scratch or newly allocated) and size
55inline void msgpack_cbind_impl(const auto& func, // The function to be applied
56 const uint8_t* input_in, // The input data in MessagePack format
57 size_t input_len_in, // The length of the input data
58 uint8_t** output_out, // IN-OUT: scratch buffer ptr / result buffer ptr
59 size_t* output_len_out) // IN-OUT: scratch buffer size / result size
60{
61 using FuncTraits = decltype(get_func_traits<decltype(func)>());
62 // Args: the parameter types of the function as a tuple.
63 typename FuncTraits::Args params;
64
65 // Unpack the input data into the parameter tuple.
66 msgpack::unpack(reinterpret_cast<const char*>(input_in), input_len_in).get().convert(params);
67
68 // Read IN values: caller-provided scratch buffer
69 uint8_t* scratch_buf = *output_out;
70 size_t scratch_size = *output_len_out;
71
72 // Apply the function to the parameters, then encode the result into a MessagePack buffer.
73 // Try to use scratch buffer; allocate if result doesn't fit.
74 auto [output, output_len] = msgpack_encode_buffer(FuncTraits::apply(func, params), scratch_buf, scratch_size);
75
76 // Write OUT values: actual result buffer and size
77 // If result fit in scratch, output == scratch_buf (pointer unchanged)
78 // If result didn't fit, output is newly allocated buffer (pointer changed)
79 *output_out = output;
80 *output_len_out = output_len;
81}
82
83// returns a C-style string json of the schema
84inline void msgpack_cbind_schema_impl(auto func, uint8_t** output_out, size_t* output_len_out)
85{
86 (void)func; // unused except for type
87 // Object representation of the cbind
88 auto cbind_obj = get_func_traits<decltype(func)>();
89 std::string schema = msgpack_schema_to_string(cbind_obj);
90 *output_out = static_cast<uint8_t*>(aligned_alloc(64, schema.size() + 1));
91 memcpy(*output_out, schema.c_str(), schema.size() + 1);
92 *output_len_out = schema.size();
93}
94
95// The CBIND_NOSCHEMA macro generates a function named 'cname' that decodes the input arguments from msgpack format,
96// calls the target function, and then encodes the return value back into msgpack format. It should be used over CBIND
97// in cases where we do not want schema generation, such as meta-functions that themselves give information to control
98// how the schema is interpreted.
99#define CBIND_NOSCHEMA(cname, func) \
100 WASM_EXPORT void cname(const uint8_t* input_in, size_t input_len_in, uint8_t** output_out, size_t* output_len_out) \
101 { \
102 msgpack_cbind_impl(func, input_in, input_len_in, output_out, output_len_out); \
103 }
104
105// The CBIND macro is a convenient utility that abstracts away several steps in binding C functions with msgpack
106// serialization. It creates two separate functions:
107// 1. cname function: This decodes the input arguments from msgpack format, calls the target function,
108// and then encodes the return value back into msgpack format.
109// 2. cname##__schema function: This creates a JSON schema of the function's input arguments and return type.
110#define CBIND(cname, func) \
111 CBIND_NOSCHEMA(cname, func) \
112 WASM_EXPORT void cname##__schema(uint8_t** output_out, size_t* output_len_out) \
113 { \
114 msgpack_cbind_schema_impl(func, output_out, output_len_out); \
115 }
std::unique_ptr< uint8_t[]> buffer
Definition engine.cpp:50
void msgpack_cbind_impl(const auto &func, const uint8_t *input_in, size_t input_len_in, uint8_t **output_out, size_t *output_len_out)
void msgpack_cbind_schema_impl(auto func, uint8_t **output_out, size_t *output_len_out)
std::pair< uint8_t *, size_t > msgpack_encode_buffer(auto &&obj, uint8_t *scratch_buf=nullptr, size_t scratch_size=0)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string msgpack_schema_to_string(const auto &obj)
Print's an object's derived msgpack schema as a string.