# We emit a C header by default. language = "C" # We use this macro to prevent double-includes of our header. include_guard = "ARTI_RPC_CLIENT_CORE_H_" # This appears at the top of the file. header = """\ /** * # Arti RPC core library header. * * ## Implementation status * * Note: As of Jan 2025, this library, and the Arti RPC system, * are still under active development. * We believe that they are ready to try out, but it is likely * that they still have bugs and design flaws that we'll need to fix. * Please be ready to report issues at * . * * We will make an effort to keep API compatibility over time, * but it's possible that we'll need to break things in small ways. * If we do, we will note them in our changelog and our announcements. * * For now, the Arti RPC interface itself provides only limited * functionality. We will add support for more features over time. * * ## Who should use this library * * You should use this library if you want to write a program that controls Arti * via its RPC interface, and you don't want to write an implementation of the RPC * protocol from scratch. * * ## What this library does * * The Arti RPC system works by establishing connections to an Arti instance, * and then exchanging requests and replies in a format inspired by * JSON-RPC. This library takes care of the work of connecting to an Arti * instance, authenticating, validating outgoing JSON requests, and matching * their corresponding JSON responses as they arrive. * * This library _does not_ do the work of creating well-formed requests, * or interpreting the responses. * * Despite this library being exposed via a set of C functions, * we don't actually expect you to use it from C. It's probably a better * idea to wrap it in a higher-level language and then use it from there. * * The `arti_rpc` python package (available from the Arti git repository) * is one example of such a wrapper. * * ## Using this library * * ### Making a connection to Arti * * First, you will need to have Arti running, and configured to use * rpc. This will eventually be the default behavior, but for now, * make sure that arti was built using the `rpc` cargo feature, and that * the configuration option `rpc.enable` is set to true. * * (For more detailed instructions on how to do this, * and for examples code, * see the Arti RPC book.) * (TODO Add link once there is one.) * * Your connection to Arti is represented by an `ArtiRpcConn *`. * To get one: * - Call `arti_rpc_conn_builder_new()` to make an `ArtiRpcConnBuilder`. * - Configure the `ArtiRpcConnBuilder` as needed, * to tell it where to find Arti. * (If you configured Arti as described above, * and you're running as the same user, * then no additional configuration should be necessary.) * - Call `arti_rpc_conn_builder_connect()` to try to connect to Arti. * * * * Once you have a connection, you can sent Arti various requests in * JSON format. These requests have documentation of their own; * We'll add a link to it once we've figured out where to host it. * * Use `arti_rpc_execute()` to send a simple request; the function will * return when the request succeeds, or fails. * * Except when noted otherwise, all functions in this library are thread-safe. * * ## Error handling * * On success, fallible functions return `ARTI_RPC_STATUS_SUCCESS`. On failure, * they return some other error code, and set an `* error_out` parameter * to a newly allocated `ArtiRpcError` object. * (If `error_out==NULL`, then no error is allocated.) * * You can access information about the an `ArtiRpcError` * by calling `arti_rpc_err_{status,message,response}()` on it. * When you are done with an error, you should free it with * `arti_rpc_err_free()`. * * The `error_out` parameter always appears last. * * ## Interface conventions * * - All functions check for NULL pointers in their arguments. * - As in C tor, `foo_free()` functions treat `foo_free(NULL)` as a no-op. * * - All input strings should be valid UTF-8. (The library will check.) * All output strings will be valid UTF-8. * * - Fallible functions return an ArtiStatus. * * - All identifiers are prefixed with `ARTI_RPC`, `ArtiRpc`, or `arti_rpc` as appropriate. * * - Newly allocated objects are returned via out-parameters, * with `out` in their names. * (For example, `ArtiRpcObject **out`). In such cases, `* out` will be set to a resulting object, * or to NULL if no such object is returned. Any earlier value of `*out` will be replaced * without freeing it. * (If `out` is NULL, then any object the library would have returned will instead be discarded.) * discarded. * While the function is running, * `*out` and `**out` may not be read or written by any other part of the program, * and they may not alias any other arguments.) * - Note that `*out` will be set to NULL if an error occurs * or the function's inputs are invalid. * (The `*error_out` parameter, of course, * is set to NULL when there is _no_ error, and to an error otherwise.) * * - When any object is exposed as a non-const pointer, * the application becomes the owner of that object. * The application is expected to eventually free that object via the corresponding `arti_rpc_*_free()` function. * * - When any object is exposed via a const pointer, * that object is *not* owned by the application. * That object's lifetime will be as documented. * The application must not modify or free such an object. * * - If a function should be considered a method on a given type of object, * it will take a pointer to that object as its first argument. * * - If a function consumes (takes ownership of) one of its inputs, * it does so regardless of whether the function succeeds or fails. * * - Whenever one or more functions take an argument via a `const Type *`, * it is safe to pass the same object to multiple functions at once. * (This does not apply to functions that take an argument via a * non-const pointer.) * * - Whenever a function returns an error, it returns no other newly allocated objects * besides the error object itself. * * ## Correctness requirements * * If any correctness requirements stated here or elsewhere are violated, * it is Undefined Behaviour. * Violations will not be detected by the library. * * - Basic C rules apply: * - If you pass a non-NULL pointer to a function, the pointer must be properly aligned. * It must point to valid, initialized data of the correct type. * - As an exception, functions that take a `Type **out` parameter allow the value of `*out` * (but not `out` itself!) to be uninitialized. * - If you receive data via a `const *`, you must not modify that data. * - If you receive a pointer of type `struct Type *`, * and we do not give you the definition of `struct Type`, * you must not attempt to dereference the pointer. * - You may not call any `_free()` function on an object that is currently in use. * - After you have `_freed()` an object, you may not use it again. * - Every object allocated by this library has a corresponding `*_free()` function: * You must not use libc's free() to free such objects. * - All objects passed as input to a library function must not be mutated * while that function is running. * - All objects passed as input to a library function via a non-const pointer * must not be mutated, inspected, or passed to another library function * while the function is running. * - Furthermore, if a function takes any non-const pointer arguments, * those arguments must not alias one another, * and must not alias any const arguments passed to the function. * - All `const char*` passed as inputs to library functions * are nul-terminated strings. * Additionally, they must be no larger than `SSIZE_MAX`, including the nul. * - If a function takes any mutable pointers **/""" # This appears "between major sections" autogen_warning = "/* Automatically generated by cbindgen. Don't modify manually. */" # make sure our header can be included in C++. cpp_compat = true # Consistency with Arti. tab_width = 8 after_includes = """\ /** * Type of a socket returned by RPC functions. * * This a `SOCKET` on Windows, and an fd elsewhere. **/ #ifdef _WIN32 typedef SOCKET ArtiRpcRawSocket; #else typedef int ArtiRpcRawSocket; #endif """ [defines] # This is where we would add mappings from `cfg()` to `#ifdef`. # But the only relevant cfg we have is `cfg(feature="ffi")`, # which we want to assume is always present if you're using the header. [export] # These structs are not ones we want to expose under their actual names, # or ones that we don't want to expose at all. exclude = ["FfiError", "RequestHandle", "RpcConnBuilder", "RpcConn", "RpcErrorCode", "Utf8CString", "ArtiRpcRawSocket"] [export.rename] # Having not declared these structs, we can give them new names in the # typedefs that assign them their real names. "RpcConn" = "struct ArtiRpcConn" "FfiError" = "struct ArtiRpcError" "Utf8CString" = "struct ArtiRpcStr" "RequestHandle" = "struct ArtiRpcHandle" [fn] # Lay out one argument per line. args = "vertical" [parse] [parse.expand] # We need to run our crate through macro expansion in order to get all # of the right functions and constants. # # (Unfortunately, this requires us to use nightly rust, so that cbindgen # can invoke rustc with `-Zunpretty=expanded`.) crates = ["arti-rpc-client-core"] # Run macro-expansion with --all-features so that we see `ffi`. all_features = true