mirror of
https://github.com/NixOS/nix
synced 2025-06-27 16:51:15 +02:00
The short answer for why we need to do this is so we can consistently do
`#include "nix/..."`. Without this change, there are ways to still make
that work, but they are hacky, and they have downsides such as making it
harder to make sure headers from the wrong Nix library (e..g.
`libnixexpr` headers in `libnixutil`) aren't being used.
The C API alraedy used `nix_api_*`, so its headers are *not* put in
subdirectories accordingly.
Progress on #7876
We resisted doing this for a while because it would be annoying to not
have the header source file pairs close by / easy to change file
path/name from one to the other. But I am ameliorating that with
symlinks in the next commit.
(cherry picked from commit f3e1c47f47
)
537 lines
19 KiB
C
537 lines
19 KiB
C
#ifndef NIX_API_VALUE_H
|
|
#define NIX_API_VALUE_H
|
|
|
|
/** @addtogroup libexpr
|
|
* @{
|
|
*/
|
|
/** @file
|
|
* @brief libexpr C bindings dealing with values
|
|
*/
|
|
|
|
#include "nix_api_util.h"
|
|
#include "nix_api_store.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
// cffi start
|
|
|
|
// Type definitions
|
|
typedef enum {
|
|
NIX_TYPE_THUNK,
|
|
NIX_TYPE_INT,
|
|
NIX_TYPE_FLOAT,
|
|
NIX_TYPE_BOOL,
|
|
NIX_TYPE_STRING,
|
|
NIX_TYPE_PATH,
|
|
NIX_TYPE_NULL,
|
|
NIX_TYPE_ATTRS,
|
|
NIX_TYPE_LIST,
|
|
NIX_TYPE_FUNCTION,
|
|
NIX_TYPE_EXTERNAL
|
|
} ValueType;
|
|
|
|
// forward declarations
|
|
typedef struct nix_value nix_value;
|
|
typedef struct EvalState EvalState;
|
|
|
|
[[deprecated("use nix_value instead")]] typedef nix_value Value;
|
|
|
|
// type defs
|
|
/** @brief Stores an under-construction set of bindings
|
|
* @ingroup value_manip
|
|
*
|
|
* Do not reuse.
|
|
* @see nix_make_bindings_builder, nix_bindings_builder_free, nix_make_attrs
|
|
* @see nix_bindings_builder_insert
|
|
*/
|
|
typedef struct BindingsBuilder BindingsBuilder;
|
|
|
|
/** @brief Stores an under-construction list
|
|
* @ingroup value_manip
|
|
*
|
|
* Do not reuse.
|
|
* @see nix_make_list_builder, nix_list_builder_free, nix_make_list
|
|
* @see nix_list_builder_insert
|
|
*/
|
|
typedef struct ListBuilder ListBuilder;
|
|
|
|
/** @brief PrimOp function
|
|
* @ingroup primops
|
|
*
|
|
* Owned by the GC
|
|
* @see nix_alloc_primop, nix_init_primop
|
|
*/
|
|
typedef struct PrimOp PrimOp;
|
|
/** @brief External Value
|
|
* @ingroup Externals
|
|
*
|
|
* Owned by the GC
|
|
*/
|
|
typedef struct ExternalValue ExternalValue;
|
|
|
|
/** @brief String without placeholders, and realised store paths
|
|
*/
|
|
typedef struct nix_realised_string nix_realised_string;
|
|
|
|
/** @defgroup primops Adding primops
|
|
* @{
|
|
*/
|
|
/** @brief Function pointer for primops
|
|
*
|
|
* When you want to return an error, call nix_set_err_msg(context, NIX_ERR_UNKNOWN, "your error message here").
|
|
*
|
|
* @param[in] user_data Arbitrary data that was initially supplied to nix_alloc_primop
|
|
* @param[out] context Stores error information.
|
|
* @param[in] state Evaluator state
|
|
* @param[in] args list of arguments. Note that these can be thunks and should be forced using nix_value_force before
|
|
* use.
|
|
* @param[out] ret return value
|
|
* @see nix_alloc_primop, nix_init_primop
|
|
*/
|
|
typedef void (*PrimOpFun)(
|
|
void * user_data, nix_c_context * context, EvalState * state, nix_value ** args, nix_value * ret);
|
|
|
|
/** @brief Allocate a PrimOp
|
|
*
|
|
* Owned by the garbage collector.
|
|
* Use nix_gc_decref() when you're done with the returned PrimOp.
|
|
*
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] fun callback
|
|
* @param[in] arity expected number of function arguments
|
|
* @param[in] name function name
|
|
* @param[in] args array of argument names, NULL-terminated
|
|
* @param[in] doc optional, documentation for this primop
|
|
* @param[in] user_data optional, arbitrary data, passed to the callback when it's called
|
|
* @return primop, or null in case of errors
|
|
* @see nix_init_primop
|
|
*/
|
|
PrimOp * nix_alloc_primop(
|
|
nix_c_context * context,
|
|
PrimOpFun fun,
|
|
int arity,
|
|
const char * name,
|
|
const char ** args,
|
|
const char * doc,
|
|
void * user_data);
|
|
|
|
/** @brief add a primop to the `builtins` attribute set
|
|
*
|
|
* Only applies to States created after this call.
|
|
*
|
|
* Moves your PrimOp content into the global evaluator
|
|
* registry, meaning your input PrimOp pointer is no longer usable.
|
|
* You are free to remove your references to it,
|
|
* after which it will be garbage collected.
|
|
*
|
|
* @param[out] context Optional, stores error information
|
|
* @return primop, or null in case of errors
|
|
*
|
|
*/
|
|
nix_err nix_register_primop(nix_c_context * context, PrimOp * primOp);
|
|
/** @} */
|
|
|
|
// Function prototypes
|
|
|
|
/** @brief Allocate a Nix value
|
|
*
|
|
* Owned by the GC. Use nix_gc_decref() when you're done with the pointer
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] state nix evaluator state
|
|
* @return value, or null in case of errors
|
|
*
|
|
*/
|
|
nix_value * nix_alloc_value(nix_c_context * context, EvalState * state);
|
|
|
|
/**
|
|
* @brief Increment the garbage collector reference counter for the given `nix_value`.
|
|
*
|
|
* The Nix language evaluator C API keeps track of alive objects by reference counting.
|
|
* When you're done with a refcounted pointer, call nix_value_decref().
|
|
*
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value The object to keep alive
|
|
*/
|
|
nix_err nix_value_incref(nix_c_context * context, nix_value * value);
|
|
|
|
/**
|
|
* @brief Decrement the garbage collector reference counter for the given object
|
|
*
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value The object to stop referencing
|
|
*/
|
|
nix_err nix_value_decref(nix_c_context * context, nix_value * value);
|
|
|
|
/** @addtogroup value_manip Manipulating values
|
|
* @brief Functions to inspect and change Nix language values, represented by nix_value.
|
|
* @{
|
|
*/
|
|
/** @anchor getters
|
|
* @name Getters
|
|
*/
|
|
/**@{*/
|
|
/** @brief Get value type
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return type of nix value
|
|
*/
|
|
ValueType nix_get_type(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get type name of value as defined in the evaluator
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return type name, owned string
|
|
* @todo way to free the result
|
|
*/
|
|
const char * nix_get_typename(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get boolean value
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return true or false, error info via context
|
|
*/
|
|
bool nix_get_bool(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get the raw string
|
|
*
|
|
* This may contain placeholders.
|
|
*
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @param[in] callback Called with the string value.
|
|
* @param[in] user_data optional, arbitrary data, passed to the callback when it's called.
|
|
* @return string
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err
|
|
nix_get_string(nix_c_context * context, const nix_value * value, nix_get_string_callback callback, void * user_data);
|
|
|
|
/** @brief Get path as string
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return string, if the type is NIX_TYPE_PATH
|
|
* @return NULL in case of error.
|
|
*/
|
|
const char * nix_get_path_string(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get the length of a list
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return length of list, error info via context
|
|
*/
|
|
unsigned int nix_get_list_size(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get the element count of an attrset
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return attrset element count, error info via context
|
|
*/
|
|
unsigned int nix_get_attrs_size(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get float value in 64 bits
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return float contents, error info via context
|
|
*/
|
|
double nix_get_float(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get int value
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return int contents, error info via context
|
|
*/
|
|
int64_t nix_get_int(nix_c_context * context, const nix_value * value);
|
|
|
|
/** @brief Get external reference
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @return reference to external, NULL in case of error
|
|
*/
|
|
ExternalValue * nix_get_external(nix_c_context * context, nix_value * value);
|
|
|
|
/** @brief Get the ix'th element of a list
|
|
*
|
|
* Owned by the GC. Use nix_gc_decref when you're done with the pointer
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @param[in] state nix evaluator state
|
|
* @param[in] ix list element to get
|
|
* @return value, NULL in case of errors
|
|
*/
|
|
nix_value * nix_get_list_byidx(nix_c_context * context, const nix_value * value, EvalState * state, unsigned int ix);
|
|
|
|
/** @brief Get an attr by name
|
|
*
|
|
* Owned by the GC. Use nix_gc_decref when you're done with the pointer
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @param[in] state nix evaluator state
|
|
* @param[in] name attribute name
|
|
* @return value, NULL in case of errors
|
|
*/
|
|
nix_value * nix_get_attr_byname(nix_c_context * context, const nix_value * value, EvalState * state, const char * name);
|
|
|
|
/** @brief Check if an attribute name exists on a value
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @param[in] state nix evaluator state
|
|
* @param[in] name attribute name
|
|
* @return value, error info via context
|
|
*/
|
|
bool nix_has_attr_byname(nix_c_context * context, const nix_value * value, EvalState * state, const char * name);
|
|
|
|
/** @brief Get an attribute by index in the sorted bindings
|
|
*
|
|
* Also gives you the name.
|
|
*
|
|
* Owned by the GC. Use nix_gc_decref when you're done with the pointer
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @param[in] state nix evaluator state
|
|
* @param[in] i attribute index
|
|
* @param[out] name will store a pointer to the attribute name
|
|
* @return value, NULL in case of errors
|
|
*/
|
|
nix_value * nix_get_attr_byidx(
|
|
nix_c_context * context, const nix_value * value, EvalState * state, unsigned int i, const char ** name);
|
|
|
|
/** @brief Get an attribute name by index in the sorted bindings
|
|
*
|
|
* Useful when you want the name but want to avoid evaluation.
|
|
*
|
|
* Owned by the nix EvalState
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value to inspect
|
|
* @param[in] state nix evaluator state
|
|
* @param[in] i attribute index
|
|
* @return name, NULL in case of errors
|
|
*/
|
|
const char *
|
|
nix_get_attr_name_byidx(nix_c_context * context, const nix_value * value, EvalState * state, unsigned int i);
|
|
|
|
/**@}*/
|
|
/** @name Initializers
|
|
*
|
|
* Values are typically "returned" by initializing already allocated memory that serves as the return value.
|
|
* For this reason, the construction of values is not tied their allocation.
|
|
* Nix is a language with immutable values. Respect this property by only initializing Values once; and only initialize
|
|
* Values that are meant to be initialized by you. Failing to adhere to these rules may lead to undefined behavior.
|
|
*/
|
|
/**@{*/
|
|
/** @brief Set boolean value
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] b the boolean value
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_init_bool(nix_c_context * context, nix_value * value, bool b);
|
|
|
|
/** @brief Set a string
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] str the string, copied
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_init_string(nix_c_context * context, nix_value * value, const char * str);
|
|
|
|
/** @brief Set a path
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] str the path string, copied
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_init_path_string(nix_c_context * context, EvalState * s, nix_value * value, const char * str);
|
|
|
|
/** @brief Set a float
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] d the float, 64-bits
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_init_float(nix_c_context * context, nix_value * value, double d);
|
|
|
|
/** @brief Set an int
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] i the int
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
|
|
nix_err nix_init_int(nix_c_context * context, nix_value * value, int64_t i);
|
|
/** @brief Set null
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_init_null(nix_c_context * context, nix_value * value);
|
|
|
|
/** @brief Set the value to a thunk that will perform a function application when needed.
|
|
*
|
|
* Thunks may be put into attribute sets and lists to perform some computation lazily; on demand.
|
|
* However, note that in some places, a thunk must not be returned, such as in the return value of a PrimOp.
|
|
* In such cases, you may use nix_value_call() instead (but note the different argument order).
|
|
*
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] fn function to call
|
|
* @param[in] arg argument to pass
|
|
* @return error code, NIX_OK on successful initialization.
|
|
* @see nix_value_call() for a similar function that performs the call immediately and only stores the return value.
|
|
* Note the different argument order.
|
|
*/
|
|
nix_err nix_init_apply(nix_c_context * context, nix_value * value, nix_value * fn, nix_value * arg);
|
|
|
|
/** @brief Set an external value
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] val the external value to set. Will be GC-referenced by the value.
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_init_external(nix_c_context * context, nix_value * value, ExternalValue * val);
|
|
|
|
/** @brief Create a list from a list builder
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] list_builder list builder to use. Make sure to unref this afterwards.
|
|
* @param[out] value Nix value to modify
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_make_list(nix_c_context * context, ListBuilder * list_builder, nix_value * value);
|
|
|
|
/** @brief Create a list builder
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] state nix evaluator state
|
|
* @param[in] capacity how many bindings you'll add. Don't exceed.
|
|
* @return owned reference to a list builder. Make sure to unref when you're done.
|
|
*/
|
|
ListBuilder * nix_make_list_builder(nix_c_context * context, EvalState * state, size_t capacity);
|
|
|
|
/** @brief Insert bindings into a builder
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] list_builder ListBuilder to insert into
|
|
* @param[in] index index to manipulate
|
|
* @param[in] value value to insert
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err
|
|
nix_list_builder_insert(nix_c_context * context, ListBuilder * list_builder, unsigned int index, nix_value * value);
|
|
|
|
/** @brief Free a list builder
|
|
*
|
|
* Does not fail.
|
|
* @param[in] list_builder The builder to free.
|
|
*/
|
|
void nix_list_builder_free(ListBuilder * list_builder);
|
|
|
|
/** @brief Create an attribute set from a bindings builder
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] b bindings builder to use. Make sure to unref this afterwards.
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_make_attrs(nix_c_context * context, nix_value * value, BindingsBuilder * b);
|
|
|
|
/** @brief Set primop
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] op primop, will be gc-referenced by the value
|
|
* @see nix_alloc_primop
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_init_primop(nix_c_context * context, nix_value * value, PrimOp * op);
|
|
/** @brief Copy from another value
|
|
* @param[out] context Optional, stores error information
|
|
* @param[out] value Nix value to modify
|
|
* @param[in] source value to copy from
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err nix_copy_value(nix_c_context * context, nix_value * value, const nix_value * source);
|
|
/**@}*/
|
|
|
|
/** @brief Create a bindings builder
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] state nix evaluator state
|
|
* @param[in] capacity how many bindings you'll add. Don't exceed.
|
|
* @return owned reference to a bindings builder. Make sure to unref when you're
|
|
done.
|
|
*/
|
|
BindingsBuilder * nix_make_bindings_builder(nix_c_context * context, EvalState * state, size_t capacity);
|
|
|
|
/** @brief Insert bindings into a builder
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] builder BindingsBuilder to insert into
|
|
* @param[in] name attribute name, only used for the duration of the call.
|
|
* @param[in] value value to give the binding
|
|
* @return error code, NIX_OK on success.
|
|
*/
|
|
nix_err
|
|
nix_bindings_builder_insert(nix_c_context * context, BindingsBuilder * builder, const char * name, nix_value * value);
|
|
|
|
/** @brief Free a bindings builder
|
|
*
|
|
* Does not fail.
|
|
* @param[in] builder the builder to free
|
|
*/
|
|
void nix_bindings_builder_free(BindingsBuilder * builder);
|
|
/**@}*/
|
|
|
|
/** @brief Realise a string context.
|
|
*
|
|
* This will
|
|
* - realise the store paths referenced by the string's context, and
|
|
* - perform the replacement of placeholders.
|
|
* - create temporary garbage collection roots for the store paths, for
|
|
* the lifetime of the current process.
|
|
* - log to stderr
|
|
*
|
|
* @param[out] context Optional, stores error information
|
|
* @param[in] value Nix value, which must be a string
|
|
* @param[in] state Nix evaluator state
|
|
* @param[in] isIFD If true, disallow derivation outputs if setting `allow-import-from-derivation` is false.
|
|
You should set this to true when this call is part of a primop.
|
|
You should set this to false when building for your application's purpose.
|
|
* @return NULL if failed, are a new nix_realised_string, which must be freed with nix_realised_string_free
|
|
*/
|
|
nix_realised_string * nix_string_realise(nix_c_context * context, EvalState * state, nix_value * value, bool isIFD);
|
|
|
|
/** @brief Start of the string
|
|
* @param[in] realised_string
|
|
* @return pointer to the start of the string. It may not be null-terminated.
|
|
*/
|
|
const char * nix_realised_string_get_buffer_start(nix_realised_string * realised_string);
|
|
|
|
/** @brief Length of the string
|
|
* @param[in] realised_string
|
|
* @return length of the string in bytes
|
|
*/
|
|
size_t nix_realised_string_get_buffer_size(nix_realised_string * realised_string);
|
|
|
|
/** @brief Number of realised store paths
|
|
* @param[in] realised_string
|
|
* @return number of realised store paths that were referenced by the string via its context
|
|
*/
|
|
size_t nix_realised_string_get_store_path_count(nix_realised_string * realised_string);
|
|
|
|
/** @brief Get a store path. The store paths are stored in an arbitrary order.
|
|
* @param[in] realised_string
|
|
* @param[in] index index of the store path, must be less than the count
|
|
* @return store path
|
|
*/
|
|
const StorePath * nix_realised_string_get_store_path(nix_realised_string * realised_string, size_t index);
|
|
|
|
/** @brief Free a realised string
|
|
* @param[in] realised_string
|
|
*/
|
|
void nix_realised_string_free(nix_realised_string * realised_string);
|
|
|
|
// cffi end
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/** @} */
|
|
#endif // NIX_API_VALUE_H
|