
# 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
 * <https://gitlab.torproject.org/tpo/core/arti>.
 *
 * 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.
 *
 * <!-- TODO: We'll want to have documentation about connect points,
 *  but it won't go here. -->
 *
 * 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
