// Copyright 2025 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.

// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.

// This file is generated by cbindgen. Do not edit by hand.
// Version: 0.91.0-dev


#ifndef c2pa_bindings_h
#define c2pa_bindings_h

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#if defined(C2PA_DYNAMIC_LOADING) && C2PA_DYNAMIC_LOADING
#define C2PA_API

#if defined (_WIN32) || defined (WIN32)
    #ifndef _UNICODE
        #define C2PADLL_NAME "c2pa_c.dll"
    #else //_UNICODE
        #define C2PADLL_NAME L"c2pa_c.dll"
    #endif
#elif defined(__APPLE__) && defined(__MACH__)
    #define C2PADLL_NAME "libc2pa_c.dylib"
#else
    #define C2PADLL_NAME "libc2pa_c.so"
#endif //!defined(_WIN32) || defined (WIN32)

#if defined (_WIN32) || defined (WIN32)
    #undef __TEXT
    #include <windows.h>
    static HMODULE c2pa_module=NULL;
#else
    #include <dlfcn.h>
    static void* c2pa_module=NULL;
#endif

#if defined (_WIN32) || defined (WIN32)
    #define ASSIGN(_Module, _Name) \
        _Name=(_Module##_##_Name)GetProcAddress(_Module, #_Name); \
        if (_Name==NULL) Error=true;
    #define DLOPEN(_Module, _Name) \
            _Module=LoadLibrary(_Name);
    #define DLCLOSE(_Module) \
        FreeLibrary(_Module);
#else
    #define ASSIGN(_Module, _Name) \
        _Name=(_Module##_##_Name)dlsym(_Module, #_Name); \
        if (_Name==NULL) Error=true;
    #define DLOPEN(_Module, _Name) \
        _Module=dlopen(_Name, RTLD_LAZY); \
        if (!_Module) \
            _Module=dlopen("./" _Name, RTLD_LAZY); \
        if (!_Module) \
            _Module=dlopen("/usr/local/lib/" _Name, RTLD_LAZY); \
        if (!_Module) \
            _Module=dlopen("/usr/local/lib64/" _Name, RTLD_LAZY); \
        if (!_Module) \
            _Module=dlopen("/usr/lib/" _Name, RTLD_LAZY); \
        if (!_Module) \
            _Module=dlopen("/usr/lib64/" _Name, RTLD_LAZY);
    #define DLCLOSE(_Module) \
        dlclose(_Module);
#endif //defined (_WIN32) || defined (WIN32)

#else
    #if defined(_WIN32) || defined(_WIN64)
        #if defined(C2PA_DLL) && C2PA_DLL
            #if defined(__GNUC__) && __GNUC__
                #define C2PA_API __attribute__((dllexport))
            #else
                #define C2PA_API __declspec(dllexport)
            #endif
        #else
            #if defined(__GNUC__) && __GNUC__
                #define C2PA_API __attribute__((dllimport))
            #else
                #define C2PA_API __declspec(dllimport)
            #endif
        #endif
    #else
        #if defined(__GNUC__) && __GNUC__
            #define C2PA_API __attribute__((visibility("default")))
        #else
            #define C2PA_API
        #endif
    #endif
#endif

/* Deprecation macros: produce compiler warnings when deprecated C2PA functions are called.
 * GCC/Clang __attribute__ is checked first because it is position-flexible
 * (works after 'extern'), whereas C++ [[deprecated]] is only valid at the
 * very start of a declaration and cbindgen emits the annotation after the
 * 'extern' keyword. */
#if defined(__GNUC__) || defined(__clang__)
    #define C2PA_DEPRECATED __attribute__((deprecated))
    #define C2PA_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
#elif defined(__cplusplus) && __cplusplus >= 201402L
    #define C2PA_DEPRECATED [[deprecated]]
    #define C2PA_DEPRECATED_MSG(msg) [[deprecated(msg)]]
#elif defined(_MSC_VER)
    #define C2PA_DEPRECATED __declspec(deprecated)
    #define C2PA_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
#else
    #define C2PA_DEPRECATED
    #define C2PA_DEPRECATED_MSG(msg)
#endif




/**
 * Maximum length for C strings when using bounded conversion (64KB)
 */
#define MAX_CSTRING_LEN 1048576

/**
 * Maximum number of entries accepted from a NULL-terminated C string array.
 * Guards against runaway iteration when a caller omits the NULL terminator.
 */
#define MAX_STRING_ARRAY_LEN 256

/**
 * Defines the seek mode for the seek callback.
 */
typedef enum C2paSeekMode {
  /**
   * Seeks from the start of the stream.
   */
  Start = 0,
  /**
   * Seeks from the current position in the stream.
   */
  Current = 1,
  /**
   * Seeks from the end of the stream.
   */
  End = 2,
} C2paSeekMode;

/**
 * Progress phase constants passed to C progress callbacks.
 * These mirror [`c2pa::ProgressPhase`] variants.
 */
typedef enum C2paProgressPhase {
  Reading = 0,
  VerifyingManifest = 1,
  VerifyingSignature = 2,
  VerifyingIngredient = 3,
  VerifyingAssetHash = 4,
  AddingIngredient = 5,
  Thumbnail = 6,
  Hashing = 7,
  Signing = 8,
  Embedding = 9,
  FetchingRemoteManifest = 10,
  Writing = 11,
  FetchingOCSP = 12,
  FetchingTimestamp = 13,
} C2paProgressPhase;

/**
 * Builder intent enumeration.
 * This specifies what kind of manifest to create.
 */
typedef enum C2paBuilderIntent {
  /**
   * This is a new digital creation with the specified digital source type.
   * The Manifest must not have a parent ingredient.
   * A `c2pa.created` action will be added if not provided.
   */
  Create,
  /**
   * This is an edit of a pre-existing parent asset.
   * The Manifest must have a parent ingredient.
   * A parent ingredient will be generated from the source stream if not otherwise provided.
   * A `c2pa.opened` action will be tied to the parent ingredient.
   */
  Edit,
  /**
   * A restricted version of Edit for non-editorial changes.
   * There must be only one ingredient, as a parent.
   * No changes can be made to the hashed content of the parent.
   */
  Update,
} C2paBuilderIntent;

/**
 * List of possible digital source types.
 */
typedef enum C2paDigitalSourceType {
  Empty,
  TrainedAlgorithmicData,
  DigitalCapture,
  ComputationalCapture,
  NegativeFilm,
  PositiveFilm,
  Print,
  HumanEdits,
  CompositeWithTrainedAlgorithmicMedia,
  AlgorithmicallyEnhanced,
  DigitalCreation,
  DataDrivenMedia,
  TrainedAlgorithmicMedia,
  AlgorithmicMedia,
  ScreenCapture,
  VirtualRecording,
  Composite,
  CompositeCapture,
  CompositeSynthetic,
} C2paDigitalSourceType;

/**
 * Hash binding type for embeddable signing workflows.
 */
typedef enum C2paHashType {
  /**
   * Placeholder + exclusions + hash + sign (JPEG, PNG, etc.).
   */
  DataHash = 0,
  /**
   * Placeholder + hash + sign (MP4, AVIF, HEIF/HEIC).
   */
  BmffHash = 1,
  /**
   * Hash + sign, no placeholder needed.
   */
  BoxHash = 2,
} C2paHashType;

/**
 * List of supported signing algorithms.
 */
typedef enum C2paSigningAlg {
  Es256,
  Es384,
  Es512,
  Ps256,
  Ps384,
  Ps512,
  Ed25519,
} C2paSigningAlg;

typedef struct C2paSigner C2paSigner;

/**
 * An opaque struct to hold a context value for the stream callbacks.
 */
typedef struct StreamContext {

} StreamContext;

/**
 * Defines a callback to read from a stream.
 *
 * The return value is the number of bytes read, or a negative number for an error.
 */
typedef intptr_t (*ReadCallback)(struct StreamContext *context, uint8_t *data, intptr_t len);

/**
 * Defines a callback to seek to an offset in a stream.
 *
 * The return value is the new position in the stream, or a negative number for an error.
 */
typedef intptr_t (*SeekCallback)(struct StreamContext *context,
                                 intptr_t offset,
                                 enum C2paSeekMode mode);

/**
 * Defines a callback to write to a stream.
 *
 * The return value is the number of bytes written, or a negative number for an error.
 */
typedef intptr_t (*WriteCallback)(struct StreamContext *context, const uint8_t *data, intptr_t len);

/**
 * Defines a callback to flush a stream.
 *
 * The return value is 0 for success, or a negative number for an error.
 */
typedef intptr_t (*FlushCallback)(struct StreamContext *context);

/**
 * A C2paStream is a Rust Read/Write/Seek stream that can be created and used in C.
 */
typedef struct C2paStream {
  struct StreamContext *context;
  ReadCallback reader;
  SeekCallback seeker;
  WriteCallback writer;
  FlushCallback flusher;
} C2paStream;

typedef struct C2paSettings {

} C2paSettings;

typedef struct C2paContextBuilder {

} C2paContextBuilder;

/**
 * C-callable progress callback function type.
 *
 * # Parameters
 * * `context` – the opaque `user_data` pointer passed to
 *   `c2pa_context_builder_set_progress_callback`.
 * * `phase`   – a [`C2paProgressPhase`] value identifying the current operation.
 *   Callers should derive any user-visible text from this value in the appropriate language.
 * * `step`    – monotonically increasing counter within the current phase, starting at
 *   `1`.  Resets to `1` at the start of each new phase.  Use as a liveness heartbeat:
 *   a rising `step` means the SDK is making forward progress.  The unit is
 *   phase-specific and should otherwise be treated as opaque.
 * * `total`   – `0` = indeterminate (show a spinner, use `step` as liveness signal);
 *   `1` = single-shot phase (the callback itself is the notification);
 *   `> 1` = determinate (`step / total` gives a completion fraction for a progress bar).
 *
 * # Return value
 * Return non-zero to continue the operation, zero to cancel.
 */
typedef int (*ProgressCCallback)(const void *context,
                                 enum C2paProgressPhase phase,
                                 uint32_t step,
                                 uint32_t total);

typedef struct C2paHttpResolver {

} C2paHttpResolver;

/**
 * HTTP request passed to the resolver callback.
 *
 * All string fields are NULL-terminated UTF-8. The struct and all
 * pointed-to data remain valid for the duration of the callback.
 */
typedef struct C2paHttpRequest {
  /**
   * URL (e.g. `https://example.com/manifest`)
   */
  const char *url;
  /**
   * HTTP method (e.g. "GET", "POST")
   */
  const char *method;
  /**
   * Newline-delimited "Name: Value\n" pairs, or NULL if none
   */
  const char *headers;
  /**
   * Request body bytes, or NULL if none
   */
  const unsigned char *body;
  /**
   * Length of `body` in bytes
   */
  uintptr_t body_len;
} C2paHttpRequest;

/**
 * HTTP response filled in by the resolver callback.
 *
 * The callback must set `status`, `body`, and `body_len`.
 * `body` must be allocated with `malloc()`. Rust will call `free()` on it
 * after copying the data.
 */
typedef struct C2paHttpResponse {
  /**
   * HTTP status code (e.g. 200, 404)
   */
  int32_t status;
  /**
   * Response body bytes, allocated by the callback with `malloc()`.
   * Rust takes ownership and will call `free()`.
   */
  unsigned char *body;
  /**
   * Length of `body` in bytes
   */
  uintptr_t body_len;
} C2paHttpResponse;

/**
 * Callback type for custom HTTP request resolution.
 *
 * Called synchronously by Rust when an HTTP request is needed
 * (remote manifest fetch, OCSP, timestamp, etc.).
 *
 * Returns 0 on success, non-zero on error. On error, call
 * `c2pa_error_set_last()` before returning.
 */
typedef int (*C2paHttpResolverCallback)(void *context,
                                        const struct C2paHttpRequest *request,
                                        struct C2paHttpResponse *response);

typedef struct C2paContext {

} C2paContext;

typedef struct C2paReader {

} C2paReader;

typedef struct C2paBuilder {

} C2paBuilder;

/**
 * Defines a callback to read from a stream.
 *
 * # Parameters
 * * context: A generic context value to used by the C code, often a file or stream reference.
 */
typedef intptr_t (*SignerCallback)(const void *context,
                                   const unsigned char *data,
                                   uintptr_t len,
                                   unsigned char *signed_bytes,
                                   uintptr_t signed_len);

/**
 * Defines the configuration for a Signer.
 *
 * The signer is created from the sign_cert and private_key fields.
 * an optional url to an RFC 3161 compliant time server will ensure the signature is timestamped.
 */
typedef struct C2paSignerInfo {
  /**
   * The signing algorithm.
   */
  const char *alg;
  /**
   * The public certificate chain in PEM format.
   */
  const char *sign_cert;
  /**
   * The private key in PEM format.
   */
  const char *private_key;
  /**
   * The timestamp authority URL or NULL.
   */
  const char *ta_url;
} C2paSignerInfo;

#if defined(C2PA_DYNAMIC_LOADING) && C2PA_DYNAMIC_LOADING

//---------------------------------------------------------------------------
typedef int (*c2pa_module_c2pa_free)(const void*); static c2pa_module_c2pa_free c2pa_free=NULL;
typedef struct C2paContext* (*c2pa_module_c2pa_context_new)(void); static c2pa_module_c2pa_context_new c2pa_context_new=NULL;
typedef struct C2paReader* (*c2pa_module_c2pa_reader_from_context)(C2paContext*); static c2pa_module_c2pa_reader_from_context c2pa_reader_from_context=NULL;
typedef struct C2paStream* (*c2pa_module_c2pa_create_stream)(struct StreamContext*, ReadCallback, SeekCallback, WriteCallback, FlushCallback); static c2pa_module_c2pa_create_stream c2pa_create_stream=NULL;
typedef void (*c2pa_module_c2pa_release_stream)(struct C2paStream*); static c2pa_module_c2pa_release_stream c2pa_release_stream=NULL;
typedef struct C2paReader* (*c2pa_module_c2pa_reader_with_stream)(struct C2paReader*, const char*, struct C2paStream*); static c2pa_module_c2pa_reader_with_stream c2pa_reader_with_stream=NULL;
typedef char* (*c2pa_module_c2pa_reader_detailed_json)(struct C2paReader*); static c2pa_module_c2pa_reader_detailed_json c2pa_reader_detailed_json=NULL;
typedef char* (*c2pa_module_c2pa_reader_crjson)(struct C2paReader*); static c2pa_module_c2pa_reader_crjson c2pa_reader_crjson=NULL;
typedef char* (*c2pa_module_c2pa_error)(void); static c2pa_module_c2pa_error c2pa_error=NULL;
typedef struct C2paBuilder* (*c2pa_module_c2pa_builder_from_context)(struct C2paContext*); static c2pa_module_c2pa_builder_from_context c2pa_builder_from_context=NULL;
typedef struct C2paBuilder* (*c2pa_module_c2pa_builder_with_definition)(struct C2paBuilder*, const char*); static c2pa_module_c2pa_builder_with_definition c2pa_builder_with_definition=NULL;
typedef struct C2paSigner* (*c2pa_module_c2pa_signer_from_info)(const struct C2paSignerInfo*); static c2pa_module_c2pa_signer_from_info c2pa_signer_from_info=NULL;
typedef int64_t (*c2pa_module_c2pa_builder_sign)(struct C2paBuilder*, const char*, struct C2paStream*, struct C2paStream*, struct C2paSigner*, const unsigned char**); static c2pa_module_c2pa_builder_sign c2pa_builder_sign=NULL;

//---------------------------------------------------------------------------
static inline bool c2pa_load(void)
{
    bool Error=false;

    if (c2pa_module)
        return true;

    DLOPEN(c2pa_module, C2PADLL_NAME);
    if (!c2pa_module)
        return false;

    ASSIGN(c2pa_module, c2pa_free);
    ASSIGN(c2pa_module, c2pa_context_new);
    ASSIGN(c2pa_module, c2pa_reader_from_context);
    ASSIGN(c2pa_module, c2pa_create_stream);
    ASSIGN(c2pa_module, c2pa_release_stream);
    ASSIGN(c2pa_module, c2pa_reader_with_stream);
    ASSIGN(c2pa_module, c2pa_reader_detailed_json);
    ASSIGN(c2pa_module, c2pa_reader_crjson);
    ASSIGN(c2pa_module, c2pa_error);
    ASSIGN(c2pa_module, c2pa_builder_from_context);
    ASSIGN(c2pa_module, c2pa_builder_with_definition);
    ASSIGN(c2pa_module, c2pa_signer_from_info);
    ASSIGN(c2pa_module, c2pa_builder_sign);

    if (Error)
    {
        DLCLOSE(c2pa_module);
        c2pa_module=NULL;
        c2pa_free=NULL;
        c2pa_context_new=NULL;
        c2pa_reader_from_context=NULL;
        c2pa_create_stream=NULL;
        c2pa_release_stream=NULL;
        c2pa_reader_with_stream=NULL;
        c2pa_reader_detailed_json=NULL;
        c2pa_reader_crjson=NULL;
        c2pa_error=NULL;
        c2pa_builder_from_context=NULL;
        c2pa_builder_with_definition=NULL;
        c2pa_signer_from_info=NULL;
        c2pa_builder_sign=NULL;
        return false;
    }

    return true;
}

//---------------------------------------------------------------------------
static inline void c2pa_unload(void)
{
    if (c2pa_module)
    {
        DLCLOSE(c2pa_module);
        c2pa_module=NULL;
    }

    c2pa_free=NULL;
    c2pa_context_new=NULL;
    c2pa_reader_from_context=NULL;
    c2pa_create_stream=NULL;
    c2pa_release_stream=NULL;
    c2pa_reader_with_stream=NULL;
    c2pa_reader_detailed_json=NULL;
    c2pa_reader_crjson=NULL;
    c2pa_error=NULL;
    c2pa_builder_from_context=NULL;
    c2pa_builder_with_definition=NULL;
    c2pa_signer_from_info=NULL;
    c2pa_builder_sign=NULL;
}
#else
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/**
 * Creates a new C2paStream from context with callbacks.
 *
 * This allows implementing streams in other languages.
 *
 * # Arguments
 * * `context` - a pointer to a StreamContext
 * * `read` - a ReadCallback to read from the stream
 * * `seek` - a SeekCallback to seek in the stream
 * * `write` - a WriteCallback to write to the stream
 *
 * # Safety
 * The context must remain valid for the lifetime of the C2paStream.
 *
 * The resulting C2paStream must be released by calling c2pa_release_stream.
 */
C2PA_API extern
struct C2paStream *c2pa_create_stream(struct StreamContext *context,
                                      ReadCallback reader,
                                      SeekCallback seeker,
                                      WriteCallback writer,
                                      FlushCallback flusher);

/**
 * Releases a C2paStream allocated by Rust.
 *
 * # Safety
 * Can only be released once and is invalid after this call.
 */
C2PA_API extern void c2pa_release_stream(struct C2paStream *stream);

/**
 * Returns a version string for logging.
 *
 * # Safety
 * The returned value MUST be released by calling release_string
 * and it is no longer valid after that call.
 */
C2PA_API extern char *c2pa_version(void);

/**
 * Returns the last error message.
 *
 * # Safety
 * The returned value MUST be released by calling release_string
 * and it is no longer valid after that call.
 */
C2PA_API extern char *c2pa_error(void);

/**
 * Sets the last error message.
 * This is used by callbacks so they can set a return error message.
 * THe error should be in the form of "ErrorType: ErrorMessage".
 * If ErrorType is missing or invalid, it will be set to "Other".
 * and the message will include the original error string.
 * Can return -1 if the error string is NULL.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 */
C2PA_API extern int c2pa_error_set_last(const char *error_str);

/**
 * Load Settings from a string.
 * Sets thread-local settings.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_settings_new() and c2pa_context_builder_set_settings() to configure a context explicitly.")
int c2pa_load_settings(const char *settings,
                       const char *format);

/**
 * Creates a new C2PA settings object with default values.
 *
 * # Safety
 *
 * The returned pointer must be freed with `c2pa_free()`.
 *
 * # Returns
 *
 * A pointer to a newly allocated C2paSettings object, or NULL on allocation failure.
 */
C2PA_API extern struct C2paSettings *c2pa_settings_new(void);

/**
 * Updates settings from a JSON or TOML string.
 *
 * # Safety
 *
 * * `settings` must be a valid pointer to a C2paSettings object previously
 *   created by `c2pa_settings_new()` and not yet freed.
 * * `settings_str` must be a valid pointer to a null-terminated UTF-8 string.
 * * `format` must be a valid pointer to a null-terminated string containing
 *   either "json" or "toml".
 * * The pointers must remain valid for the duration of this call.
 * * This function is not thread-safe - do not call concurrently on the same `settings`.
 *
 * # Returns
 *
 * 0 on success, negative value on error.
 */
C2PA_API extern
int c2pa_settings_update_from_string(struct C2paSettings *settings,
                                     const char *settings_str,
                                     const char *format);

/**
 * Sets a specific configuration value in the settings using dot notation.
 *
 * # Safety
 *
 * * `settings` must be a valid pointer to a C2paSettings object previously
 *   created by `c2pa_settings_new()` and not yet freed.
 * * `path` must be a valid pointer to a null-terminated UTF-8 string containing
 *   a dot-separated path (e.g., "verify.verify_after_sign").
 * * `value` must be a valid pointer to a null-terminated UTF-8 string containing
 *   a JSON value (e.g., "true", "\"ps256\"", "42").
 * * The pointers must remain valid for the duration of this call.
 * * This function is not thread-safe - do not call concurrently on the same `settings`.
 *
 * # Returns
 *
 * 0 on success, negative value on error.
 */
C2PA_API extern
int c2pa_settings_set_value(struct C2paSettings *settings,
                            const char *path,
                            const char *value);

/**
 * Creates a new context builder with default settings.
 *
 * Use this to construct a context with custom configuration. After setting up
 * the builder, call `c2pa_context_builder_build()` to create an immutable context.
 *
 * # Safety
 *
 * The returned pointer must be freed by calling
 * `c2pa_free()` or converted to a context with `c2pa_context_builder_build()`.
 *
 * # Returns
 *
 * A pointer to a newly allocated C2paContextBuilder object, or NULL on allocation failure.
 *
 * # Example
 *
 * ```c
 * // Create and configure a builder
 * C2paContextBuilder* builder = c2pa_context_builder_new();
 * C2paSettings* settings = c2pa_settings_new();
 * c2pa_settings_set_value(settings, "verify.verify_after_sign", "true");
 * c2pa_context_builder_set_settings(builder, settings);
 * c2pa_free(settings);
 *
 * // Build immutable context
 * C2paContext* ctx = c2pa_context_builder_build(builder);
 * // builder is now invalid, ctx can be shared
 * ```
 */
C2PA_API extern struct C2paContextBuilder *c2pa_context_builder_new(void);

/**
 * Updates the builder with settings.
 *
 * This configures the builder with the provided settings. The settings are cloned
 * internally, so the caller retains ownership. If this call fails, the builder
 * remains in its previous valid state.
 *
 * # Safety
 *
 * * `builder` must be a valid pointer to a C2paContextBuilder object previously
 *   created by `c2pa_context_builder_new()` and not yet built.
 * * `settings` must be a valid pointer to a C2paSettings object.
 * * The pointers must remain valid for the duration of this call.
 * * This function is not thread-safe - do not call concurrently on the same `builder`.
 *
 * # Returns
 *
 * 0 on success, negative value on error.
 */
C2PA_API extern
int c2pa_context_builder_set_settings(struct C2paContextBuilder *builder,
                                      struct C2paSettings *settings);

/**
 * Set a Signer into the Builder's context.
 * (The context will own the Signer from that point on).
 * The signer will be available via `context.signer()` after
 * building the context. If a signer is also configured in settings,
 * the programmatic signer takes priority regardless of call order.
 *
 * Works with any C2paSigner pointer, whether created by
 * `c2pa_signer_from_info` or `c2pa_signer_create`.
 *
 * # Safety
 *
 * * `builder` must be a valid C2paContextBuilder pointer (not yet built).
 * * `signer_ptr` must be a valid C2paSigner pointer. It is consumed by this
 *   call and must not be used or freed afterward.
 *
 * # Returns
 *
 * 0 on success, negative value on error.
 */
C2PA_API extern
int c2pa_context_builder_set_signer(struct C2paContextBuilder *builder,
                                    struct C2paSigner *signer_ptr);

/**
 * Attaches a C progress callback to a context builder.
 *
 * The `callback` is invoked at key checkpoints during signing and reading
 * operations.  Returning `0` from the callback requests cancellation; the SDK
 * will return an error at the next safe stopping point.
 *
 * # Parameters
 * * `builder`  – a valid `C2paContextBuilder` pointer.
 * * `user_data` – opaque `void*` captured by the closure and passed as the first argument
 *   of every `callback` invocation.  Pass `NULL` if the callback does not need user data.
 * * `callback` – C function pointer matching [`ProgressCCallback`].
 *
 * # Returns
 * `0` on success, non-zero on error (check `c2pa_error()`).
 *
 * # Safety
 * * `builder` must be valid and not yet built.
 * * `user_data` must remain valid for the entire lifetime of the built context.
 */
C2PA_API extern
int c2pa_context_builder_set_progress_callback(struct C2paContextBuilder *builder,
                                               const void *user_data,
                                               ProgressCCallback callback);

/**
 * Creates a new HTTP resolver backed by a C callback.
 *
 * The `context` pointer is passed unmodified to every callback invocation and
 * must remain valid for the lifetime of the resolver and any context built from it.
 *
 * # Safety
 *
 * * `callback` must be a valid function pointer that remains valid for the
 *   lifetime of the resolver.
 * * `context` must remain valid for the lifetime of the resolver and any
 *   context that uses it.
 * * `context` must be safe to use from any thread (i.e. the caller upholds
 *   `Send + Sync` semantics for the pointed-to data).
 *
 * # Returns
 *
 * A new `C2paHttpResolver*`, or NULL on error. Must be freed with `c2pa_free()`
 * OR consumed by `c2pa_context_builder_set_http_resolver()`.
 */
C2PA_API extern
struct C2paHttpResolver *c2pa_http_resolver_create(const void *context,
                                                   C2paHttpResolverCallback callback);

/**
 * Sets a custom HTTP resolver on the context builder.
 *
 * The builder takes ownership of the resolver; the caller must NOT free it afterward.
 *
 * # Safety
 *
 * * `builder` must be a valid C2paContextBuilder pointer (not yet built).
 * * `resolver_ptr` is consumed and must not be used or freed afterward.
 *
 * # Returns
 *
 * 0 on success, -1 on error.
 */
C2PA_API extern
int c2pa_context_builder_set_http_resolver(struct C2paContextBuilder *builder,
                                           struct C2paHttpResolver *resolver_ptr);

/**
 * Builds an immutable, shareable context from the builder.
 *
 * The builder is consumed by this operation and becomes invalid.
 * The returned context is immutable and can be shared between multiple
 * Reader and Builder instances.
 *
 * # Safety
 *
 * * `builder` must be a valid pointer to a C2paContextBuilder.
 * * After calling this function, the builder pointer is INVALID and must not be used again.
 * * The returned context must be freed with `c2pa_free()`.
 *
 * # Returns
 *
 * A pointer to an immutable C2paContext that can be shared, or NULL on error.
 */
C2PA_API extern struct C2paContext *c2pa_context_builder_build(struct C2paContextBuilder *builder);

/**
 * Creates a new immutable context with default settings.
 *
 * This is a convenience function equivalent to:
 * ```c
 * builder = c2pa_context_builder_new();
 * ctx = c2pa_context_builder_build(builder);
 * ```
 *
 * Use `c2pa_context_builder_new()` if you need to configure the context
 * before building it.
 *
 * # Safety
 *
 * The returned pointer must be freed with `c2pa_free()`.
 *
 * # Returns
 *
 * A pointer to a newly allocated immutable C2paContext object, or NULL on allocation failure.
 */
C2PA_API extern struct C2paContext *c2pa_context_new(void);

/**
 * Requests cancellation of any in-progress operation on this context.
 *
 * Thread-safe — may be called from any thread that holds a valid `C2paContext`
 * pointer.  The SDK will return an `OperationCancelled` error at the next safe
 * checkpoint inside the running operation.
 *
 * # Parameters
 * * `ctx` – a valid, non-null `C2paContext` pointer obtained from
 *   `c2pa_context_builder_build()` or `c2pa_context_new()`.
 *
 * # Returns
 * `0` on success, non-zero if `ctx` is null or invalid.
 *
 * # Safety
 * `ctx` must be a valid pointer and must not be freed concurrently with this call.
 */
C2PA_API extern int c2pa_context_cancel(struct C2paContext *ctx);

/**
 * Frees a string allocated by Rust.
 *
 * # Safety
 * The string must not have been modified in C.
 * The string can only be freed once and is invalid after this call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_free() instead, which works for all pointer types.")
void c2pa_release_string(char *s);

/**
 * Frees any pointer allocated by this library.
 *
 * This is the **recommended** free function for all C2PA objects. It replaces the
 * type-specific free functions (like `c2pa_string_free`, `c2pa_reader_free`, etc.)
 * which are maintained only for backward compatibility.
 *
 * ## Why use c2pa_free?
 *
 * - **Simpler API**: One function to remember instead of multiple type-specific functions
 * - **Less error-prone**: No need to match the correct free function to each type
 * - **Consistent**: Works uniformly across all pointer types
 * - **Returns error codes**: Returns 0 on success, -1 on error for better error handling
 *
 * ## Supported Types
 *
 * This function works for all C2PA objects including:
 * - C2paContext
 * - C2paSettings
 * - C2paBuilder
 * - C2paReader
 * - C2paSigner
 * - strings (c_char*)
 * - byte arrays (c_uchar*)
 * - manifest bytes
 * - signatures
 * - and any other objects created by this library
 *
 * # Safety
 *
 * * The pointer must have been allocated by this library (e.g., from c2pa_context_new(),
 *   c2pa_settings_new(), c2pa_builder_from_json(), etc.)
 * * The pointer must not have been modified in C.
 * * The pointer can only be freed once and is invalid after this call.
 * * Do not mix this with type-specific free functions for the same pointer.
 *
 * # Returns
 *
 * 0 on success, -1 on error (e.g., if the pointer was not allocated by this library).
 *
 * # Example (C)
 *
 * ```c
 * // Create various objects
 * C2paReader* reader = c2pa_reader_from_file("image.jpg", "json");
 * char* json = c2pa_reader_json(reader);
 * C2paBuilder* builder = c2pa_builder_from_json(json);
 *
 * // Free everything with the same function
 * c2pa_free(json);
 * c2pa_free(reader);
 * c2pa_free(builder);
 * ```
 */
C2PA_API extern int c2pa_free(const void *ptr);

/**
 * Frees a string allocated by Rust.
 *
 * **Note**: This function is maintained for backward compatibility. New code should
 * use [`c2pa_free`] instead, which works for all pointer types.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The string must not have been modified in C.
 * The string can only be freed once and is invalid after this call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_free() instead, which works for all pointer types.")
void c2pa_string_free(char *s);

/**
 * Frees an array of char* pointers created by Rust.
 *
 * # Parameters
 * * ptr: pointer to the array of char* pointers.
 * * count: number of elements in the array.
 *
 * # Safety
 * * The ptr passed into this function must point to memory that was allocated
 *   by our library.
 * * The array and its strings must not have been modified in C.
 * * The array and its contents can only be freed once and is invalid after this call.
 */
C2PA_API extern void c2pa_free_string_array(const char *const *ptr, uintptr_t count);

/**
 * Creates a new C2paReader from a default context.
 *
 * # Safety
 *
 * This function is safe to call with no preconditions.
 *
 * # Returns
 * A pointer to a newly allocated C2paReader, or NULL on error.
 * The returned pointer must be freed with `c2pa_free()`.
 */
C2PA_API extern struct C2paReader *c2pa_reader_new(void);

/**
 * Creates a new C2paReader from a shared context.
 *
 * The context can be reused to create multiple readers and builders.
 *
 * # Safety
 *
 * * `context` must be a valid pointer to a C2paContext object.
 * * The context pointer remains valid after this call and can be reused.
 *
 * # Returns
 *
 * A pointer to a newly allocated C2paReader, or NULL on error.
 */
C2PA_API extern struct C2paReader *c2pa_reader_from_context(struct C2paContext *context);

/**
 * # Example
 * ```c
 * auto result = c2pa_reader_from_stream("image/jpeg", stream);
 * if (result == NULL) {
 *     let error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 *
 * # Safety
 * format must be a valid NULL-terminated C string pointer.
 * stream must be a valid pointer to a C2paStream.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_reader_from_context() with an explicit context instead of relying on thread-local settings.")
struct C2paReader *c2pa_reader_from_stream(const char *format,
                                           struct C2paStream *stream);

/**
 * Configures an existing reader with a stream.
 *
 * This method consumes the original reader and returns a new configured reader.
 * The original reader pointer becomes invalid after this call.
 *
 * # Safety
 *
 * * `reader` must be a valid pointer to a C2paReader.
 * * `format` must be a valid null-terminated string with the MIME type.
 * * `stream` must be a valid pointer to a C2paStream.
 * * After calling this function, the `reader` pointer is INVALID.
 *
 * # Returns
 *
 * A pointer to a newly configured C2paReader, or NULL on error.
 */
C2PA_API extern
struct C2paReader *c2pa_reader_with_stream(struct C2paReader *reader,
                                           const char *format,
                                           struct C2paStream *stream);

/**
 * Configures an existing passed in Reader with manifest data and a stream.
 * This covers the case when a Reader needs to be able to re-read signed
 * manifest bytes. This method consumes the original Reader and returns a
 * new configured Reader. The original Reader pointer becomes invalid after
 * this call and should not be reused.
 *
 * # Safety
 *
 * * `reader` must be a valid pointer to a configured C2paReader
 *   (usually with a Context).
 * * `format` must be a valid null-terminated string with the MIME type.
 * * `stream` must be a valid pointer to a C2paStream.
 * * `manifest_data` must be a valid pointer to manifest bytes.
 * * `manifest_size` must be the length of the manifest_data buffer.
 * * After calling this function, the `reader` pointer becomes invalid.
 *
 * # Returns
 *
 * A pointer to a newly configured C2paReader, or NULL on error.
 */
C2PA_API extern
struct C2paReader *c2pa_reader_with_manifest_data_and_stream(struct C2paReader *reader,
                                                             const char *format,
                                                             struct C2paStream *stream,
                                                             const unsigned char *manifest_data,
                                                             uintptr_t manifest_size);

/**
 * Configures an existing reader with a fragment stream.
 *
 * This is used for fragmented BMFF media formats where manifests are stored
 * in separate fragments. This method consumes the original reader and returns
 * a new configured reader. The original reader pointer becomes invalid after this call.
 *
 * # Safety
 *
 * * `reader` must be a valid pointer to a C2paReader.
 * * `format` must be a valid null-terminated string with the MIME type.
 * * `stream` must be a valid pointer to a C2paStream (the main asset stream).
 * * `fragment` must be a valid pointer to a C2paStream (the fragment stream).
 * * After calling this function, the `reader` pointer is INVALID.
 *
 * # Returns
 *
 * A pointer to a newly configured C2paReader, or NULL on error.
 *
 * # Example
 *
 * ```c
 * C2paReader* reader = c2pa_reader_from_context(ctx);
 * C2paReader* new_reader = c2pa_reader_with_fragment(reader, "video/mp4", main_stream, fragment_stream);
 * // reader is now invalid, use new_reader
 * ```
 */
C2PA_API extern
struct C2paReader *c2pa_reader_with_fragment(struct C2paReader *reader,
                                             const char *format,
                                             struct C2paStream *stream,
                                             struct C2paStream *fragment);

/**
 * Creates and verifies a C2paReader from an asset stream with the given format and manifest data.
 *
 * Parameters
 * * format: pointer to a C string with the mime type or extension.
 * * stream: pointer to a C2paStream.
 * * manifest_data: pointer to the manifest data bytes.
 * * manifest_size: size of the manifest data bytes.
 *
 * # Errors
 * Returns NULL if there were errors, otherwise returns a pointer to a ManifestStore.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_reader_from_context() then c2pa_reader_with_manifest_data_and_stream() instead.")
struct C2paReader *c2pa_reader_from_manifest_data_and_stream(const char *format,
                                                             struct C2paStream *stream,
                                                             const unsigned char *manifest_data,
                                                             uintptr_t manifest_size);

/**
 * Frees a C2paReader allocated by Rust.
 *
 * **Note**: This function is maintained for backward compatibility. New code should
 * use [`c2pa_free`] instead, which works for all pointer types.
 *
 * # Safety
 * The C2paReader can only be freed once and is invalid after this call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_free() instead, which works for all pointer types.")
void c2pa_reader_free(struct C2paReader *reader_ptr);

/**
 * Returns a JSON string generated from a C2paReader.
 *
 * # Safety
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern char *c2pa_reader_json(struct C2paReader *reader_ptr);

/**
 * Returns a detailed JSON string generated from a C2paReader.
 *
 * # Safety
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern char *c2pa_reader_detailed_json(struct C2paReader *reader_ptr);

/**
 * Returns a crJSON string generated from a C2paReader.
 *
 * # Safety
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern char *c2pa_reader_crjson(struct C2paReader *reader_ptr);

/**
 * Returns the remote url of the manifest if it was obtained remotely.
 *
 * # Parameters
 * * reader_ptr: pointer to a C2paReader.
 *
 * # Safety
 * reader_ptr must be a valid pointer to a C2paReader.
 */
C2PA_API extern const char *c2pa_reader_remote_url(struct C2paReader *reader_ptr);

/**
 * Returns if the reader was created from an embedded manifest.
 *
 * # Parameters
 * * reader_ptr: pointer to a C2paReader.
 *
 * # Safety
 * reader_ptr must be a valid pointer to a C2paReader.
 */
C2PA_API extern bool c2pa_reader_is_embedded(struct C2paReader *reader_ptr);

/**
 * Writes a C2paReader resource to a stream given a URI.
 *
 * The resource uri should match an identifier in the the manifest store.
 *
 * # Parameters
 * * reader_ptr: pointer to a Reader.
 * * uri: pointer to a C string with the URI to identify the resource.
 * * stream: pointer to a writable C2paStream.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns size of stream written.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 *
 * # Example
 * ```c
 * auto result = c2pa_reader_resource_to_stream(store, "uri", stream);
 * if (result < 0) {
 *     auto error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern
int64_t c2pa_reader_resource_to_stream(struct C2paReader *reader_ptr,
                                       const char *uri,
                                       struct C2paStream *stream);

/**
 * Returns an array of char* pointers to c2pa::Reader's supported mime types.
 * The caller is responsible for freeing the array.
 *
 * # Parameters
 * * count: pointer to a usize to return the number of mime types.
 *
 * # Safety
 * The returned value MUST be released by calling [c2pa_free_string_array].
 * The array and its contents are no longer valid after that call.
 */
C2PA_API extern const char *const *c2pa_reader_supported_mime_types(uintptr_t *count);

/**
 * Creates a C2paBuilder from a JSON manifest definition string.
 *
 * # Errors
 * Returns NULL if there were errors, otherwise returns a pointer to a Builder.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 *
 * # Example
 * ```c
 * auto result = c2pa_builder_from_json(manifest_json);
 * if (result == NULL) {
 *     auto error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_builder_from_context() then c2pa_builder_set_definition() instead.")
struct C2paBuilder *c2pa_builder_from_json(const char *manifest_json);

/**
 * Creates a C2paBuilder from a shared Context.
 *
 * The context can be reused to create multiple builders and readers.
 * The builder will inherit the context's settings, signers, and resolvers.
 *
 * # Safety
 *
 * * `context` must be a valid pointer to a C2paContext object.
 * * The context pointer remains valid after this call and can be reused.
 *
 * # Returns
 *
 * A pointer to a newly allocated C2paBuilder, or NULL on error.
 *
 * # Example
 *
 * ```c
 * C2paContext* ctx = c2pa_context_new();
 * C2paBuilder* builder = c2pa_builder_from_context(ctx);
 * // context can still be used
 * C2paReader* reader = c2pa_reader_from_context(ctx);
 * ```
 */
C2PA_API extern struct C2paBuilder *c2pa_builder_from_context(struct C2paContext *context);

/**
 * Create a C2paBuilder from an archive stream.
 *
 * # Errors
 * Returns NULL if there were errors, otherwise returns a pointer to a Builder.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 *
 * # Example
 * ```c
 * auto result = c2pa_builder_from_archive(stream);
 * if (result == NULL) {
 *     auto error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_builder_from_context() then c2pa_builder_with_archive() instead.")
struct C2paBuilder *c2pa_builder_from_archive(struct C2paStream *stream);

/**
 * Returns an array of char* pointers to the supported mime types.
 * The caller is responsible for freeing the array.
 *
 * # Parameters
 * * count: pointer to a usize to return the number of mime types.
 *
 * # Safety
 * The returned value MUST be released by calling [c2pa_free_string_array].
 * The array and its contents are no longer valid after that call.
 */
C2PA_API extern const char *const *c2pa_builder_supported_mime_types(uintptr_t *count);

/**
 * Frees a C2paBuilder allocated by Rust.
 *
 * **Note**: This function is maintained for backward compatibility. New code should
 * use [`c2pa_free`] instead, which works for all pointer types.
 *
 * # Safety
 * The C2paBuilder can only be freed once and is invalid after this call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_free() instead, which works for all pointer types.")
void c2pa_builder_free(struct C2paBuilder *builder_ptr);

/**
 * Updates the builder with a new manifest definition.
 *
 * This consumes the original builder and returns a new configured builder.
 * The original builder pointer becomes invalid after this call.
 *
 * # Safety
 *
 * * `builder` must be a valid pointer to a C2paBuilder.
 * * `manifest_json` must be a valid null-terminated JSON string.
 * * After calling this function, the `builder` pointer is INVALID.
 *
 * # Returns
 *
 * A pointer to a newly configured C2paBuilder, or NULL on error.
 *
 * # Example
 *
 * ```c
 * C2paBuilder* builder = c2pa_builder_from_context(ctx);
 * const char* json = "{\"title\": \"Updated Title\"}";
 * C2paBuilder* new_builder = c2pa_builder_with_definition(builder, json);
 * // builder is now invalid, use new_builder
 * ```
 */
C2PA_API extern
struct C2paBuilder *c2pa_builder_with_definition(struct C2paBuilder *builder,
                                                 const char *manifest_json);

/**
 * Configures an existing builder with an archive stream.
 *
 * This consumes the original builder and returns a new configured builder.
 * The original builder pointer becomes invalid after this call.
 *
 * # Safety
 *
 * * `builder` must be a valid pointer to a C2paBuilder.
 * * `stream` must be a valid pointer to a C2paStream.
 * * After calling this function, the `builder` pointer is INVALID.
 *
 * # Returns
 *
 * A pointer to a newly configured C2paBuilder, or NULL on error.
 *
 * # Example
 *
 * ```c
 * C2paBuilder* builder = c2pa_builder_from_context(ctx);
 * C2paBuilder* new_builder = c2pa_builder_with_archive(builder, archive_stream);
 * // builder is now invalid, use new_builder
 * ```
 */
C2PA_API extern
struct C2paBuilder *c2pa_builder_with_archive(struct C2paBuilder *builder,
                                              struct C2paStream *stream);

/**
 * Sets the builder intent on the Builder.
 *
 * An intent lets the API know what kind of manifest to create.
 * Intents are `Create`, `Edit`, or `Update`.
 *
 * Create requires a `DigitalSourceType`. It is used for assets without a parent ingredient.
 * Edit requires a parent ingredient and is used for most assets that are being edited.
 * Update is a special case with many restrictions but is more compact than Edit.
 *
 * For the `Create` intent, a valid `digital_source_type` must be provided.
 * For `Edit` and `Update` intents, `digital_source_type` will be ignored (any value is allowed).
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * intent: the builder intent (Create, Edit, or Update).
 * * digital_source_type: the digital source type (required for Create intent).
 *
 * # Errors
 * Returns -1 if there were errors (null pointer for builder_ptr), otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * builder_ptr must be a valid pointer to a Builder.
 */
C2PA_API extern
int c2pa_builder_set_intent(struct C2paBuilder *builder_ptr,
                            enum C2paBuilderIntent intent,
                            enum C2paDigitalSourceType digital_source_type);

/**
 * Sets the no-embed flag on the Builder.
 * When set, the builder will not embed a C2PA manifest store into the asset when signing.
 * This is useful when creating cloud or sidecar manifests.
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * # Safety
 * builder_ptr must be a valid pointer to a Builder.
 */
C2PA_API extern void c2pa_builder_set_no_embed(struct C2paBuilder *builder_ptr);

/**
 * Sets the remote URL on the Builder.
 * When set, the builder will embed a remote URL into the asset when signing.
 * This is useful when creating cloud based Manifests.
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * remote_url: pointer to a C string with the remote URL.
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 * # Safety
 * Reads from NULL-terminated C strings.
 */
C2PA_API extern
int c2pa_builder_set_remote_url(struct C2paBuilder *builder_ptr,
                                const char *remote_url);

/**
 * ⚠️ **Deprecated Soon**
 * This method is planned to be deprecated in a future release.
 * Usage should be limited and temporary.
 *
 * Sets the resource directory on the Builder.
 * When set, resources that are not found in memory will be searched for in the given directory.
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * base_path: pointer to a C string with the resource directory.
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 * # Safety
 * Reads from NULL-terminated C strings.
 */
C2PA_API extern
int c2pa_builder_set_base_path(struct C2paBuilder *builder_ptr,
                               const char *base_path);

/**
 * Adds a resource to the C2paBuilder.
 *
 * The resource uri should match an identifier in the manifest definition.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * uri: pointer to a C string with the URI to identify the resource.
 * * stream: pointer to a C2paStream.
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings
 */
C2PA_API extern
int c2pa_builder_add_resource(struct C2paBuilder *builder_ptr,
                              const char *uri,
                              struct C2paStream *stream);

/**
 * Adds an ingredient to the C2paBuilder.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * ingredient_json: pointer to a C string with the JSON ingredient definition.
 * * format: pointer to a C string with the mime type or extension.
 * * source: pointer to a C2paStream.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 */
C2PA_API extern
int c2pa_builder_add_ingredient_from_stream(struct C2paBuilder *builder_ptr,
                                            const char *ingredient_json,
                                            const char *format,
                                            struct C2paStream *source);

/**
 * Adds an action to the manifest the Builder is constructing.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * action_json: JSON string containing the action data.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling [c2pa_error].
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 *
 * # Example
 * ```C
 * const char* manifest_def = "{}";
 * C2paBuilder* builder = c2pa_builder_from_json(manifest_def);
 *
 * const char* action_json = "{\n"
 *     "    \"action\": \"com.example.test-action\",\n"
 *     "    \"parameters\": {\n"
 *     "        \"key1\": \"value1\",\n"
 *     "        \"key2\": \"value2\"\n"
 *     "    }\n"
 * "}";
 *
 * int result = c2pa_builder_add_action(builder, action_json);
 * ```
 *
 * This creates a manifest with an actions assertion
 * containing the added action (excerpt of the full manifest):
 * ```json
 * "assertions": [
 *   {
 *     "label": "c2pa.actions.v2",
 *     "data": {
 *       "actions": [
 *         {
 *           "action": "c2pa.created",
 *           "digitalSourceType": "http://c2pa.org/digitalsourcetype/empty"
 *         },
 *         {
 *           "action": "com.example.test-action",
 *           "parameters": {
 *             "key2": "value2",
 *             "key1": "value1"
 *           }
 *         }
 *       ],
 *     }
 *   }
 * ]
 * ```
 */
C2PA_API extern
int c2pa_builder_add_action(struct C2paBuilder *builder_ptr,
                            const char *action_json);

/**
 * Writes an Archive of the Builder to the destination stream.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * stream: pointer to a writable C2paStream.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 *
 * # Example
 * ```c
 * auto result = c2pa_builder_to_archive(builder, stream);
 * if (result < 0) {
 *     auto error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern
int c2pa_builder_to_archive(struct C2paBuilder *builder_ptr,
                            struct C2paStream *stream);

/**
 * Adds an ingredient to the C2paBuilder from a C2PA ingredient archive stream.
 *
 * The stream must contain a C2PA ingredient archive produced by
 * `c2pa_builder_write_ingredient_archive`. Use
 * `c2pa_builder_add_ingredient_from_stream` for regular asset streams.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * stream: pointer to a readable, seekable C2paStream containing the ingredient archive.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Pointers must be valid and non-NULL.
 *
 * # Example
 * ```c
 * // Write the ingredient archive first
 * C2paStream* archive = c2pa_create_stream(...);
 * int result = c2pa_builder_write_ingredient_archive(ingredient_builder, "ingredient-id", archive);
 *
 * // Rewind and add it to the parent builder
 * c2pa_stream_seek(archive, 0, C2PA_SEEK_START);
 * result = c2pa_builder_add_ingredient_from_archive(parent_builder, archive);
 * ```
 */
C2PA_API extern
int c2pa_builder_add_ingredient_from_archive(struct C2paBuilder *builder_ptr,
                                             struct C2paStream *stream);

/**
 * Writes a single-ingredient C2PA archive to the destination stream.
 *
 * The archive can later be loaded with `c2pa_builder_add_ingredient_from_archive`.
 * This requires the `generate_c2pa_archive` builder setting to be enabled via
 * `c2pa_builder_with_settings` / `c2pa_context_with_settings` before calling.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * ingredient_id: pointer to a C string identifying the ingredient within the builder.
 * * stream: pointer to a writable C2paStream.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings. Pointers must be valid and non-NULL.
 *
 * # Example
 * ```c
 * C2paStream* archive = c2pa_create_stream(...);
 * int result = c2pa_builder_write_ingredient_archive(builder, "my-ingredient", archive);
 * if (result < 0) {
 *     char* error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern
int c2pa_builder_write_ingredient_archive(struct C2paBuilder *builder_ptr,
                                          const char *ingredient_id,
                                          struct C2paStream *stream);

/**
 * Creates and writes signed manifest from the C2paBuilder to the destination stream.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * format: pointer to a C string with the mime type or extension.
 * * source: pointer to a C2paStream.
 * * dest: pointer to a writable C2paStream.
 * * signer: pointer to a C2paSigner.
 * * c2pa_bytes_ptr: pointer to a pointer to a c_uchar to return manifest_bytes (optional, can be NULL).
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns the size of the c2pa data.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings
 * If manifest_bytes_ptr is not NULL, the returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern
int64_t c2pa_builder_sign(struct C2paBuilder *builder_ptr,
                          const char *format,
                          struct C2paStream *source,
                          struct C2paStream *dest,
                          struct C2paSigner *signer_ptr,
                          const unsigned char **manifest_bytes_ptr);

/**
 * Sign using the Signer from the Context.
 *
 * Equivalent to `c2pa_builder_sign` but the signer comes from the Builder's
 * context instead of being passed explicitly.
 *
 * If the context has no signer (neither programmatic via
 * `c2pa_context_builder_set_signer` nor from settings), an error
 * will be returned.
 *
 * # Parameters
 *
 * * `builder_ptr` - pointer to a Builder whose context has a signer set.
 * * `format` - MIME type or file extension (null-terminated C string).
 * * `source` - pointer to a readable C2paStream.
 * * `dest` - pointer to a read+write+seek C2paStream.
 * * `manifest_bytes_ptr` - out-pointer for the manifest bytes.
 *
 * # Safety
 *
 * Reads from NULL-terminated C strings.
 * The returned bytes MUST be released by calling `c2pa_free`.
 *
 * # Returns
 *
 * The length of the manifest bytes on success, or -1 on error.
 */
C2PA_API extern
int64_t c2pa_builder_sign_context(struct C2paBuilder *builder_ptr,
                                  const char *format,
                                  struct C2paStream *source,
                                  struct C2paStream *dest,
                                  const unsigned char **manifest_bytes_ptr);

/**
 * Frees a C2PA manifest returned by c2pa_builder_sign.
 *
 * **Note**: This function is maintained for backward compatibility. New code should
 * use [`c2pa_free`] instead, which works for all pointer types.
 *
 * # Safety
 * The bytes can only be freed once and are invalid after this call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_free() instead, which works for all pointer types.")
void c2pa_manifest_bytes_free(const unsigned char *manifest_bytes_ptr);

/**
 * Creates a hashed placeholder from a Builder.
 * The placeholder is used to reserve size in an asset for later signing.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * reserved_size: the size required for a signature from the intended signer.
 * * format: pointer to a C string with the mime type or extension.
 * * manifest_bytes_ptr: pointer to a pointer to a c_uchar to return manifest_bytes.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns the size of the manifest_bytes.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * If manifest_bytes_ptr is not NULL, the returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern
int64_t c2pa_builder_data_hashed_placeholder(struct C2paBuilder *builder_ptr,
                                             uintptr_t reserved_size,
                                             const char *format,
                                             const unsigned char **manifest_bytes_ptr);

/**
 * Sign a Builder using the specified signer and data hash.
 * The data hash is a JSON string containing DataHash information for the asset.
 * This is a low-level method for advanced use cases where the caller handles embedding the manifest.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * signer: pointer to a C2paSigner.
 * * data_hash: pointer to a C string with the JSON data hash.
 * * format: pointer to a C string with the mime type or extension.
 * * asset: pointer to a C2paStream (may be NULL to use pre calculated hashes).
 * * manifest_bytes_ptr: pointer to a pointer to a c_uchar to return manifest_bytes (optional, can be NULL).
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns the size of the manifest_bytes.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * If manifest_bytes_ptr is not NULL, the returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern
int64_t c2pa_builder_sign_data_hashed_embeddable(struct C2paBuilder *builder_ptr,
                                                 struct C2paSigner *signer_ptr,
                                                 const char *data_hash,
                                                 const char *format,
                                                 struct C2paStream *asset,
                                                 const unsigned char **manifest_bytes_ptr);

/**
 * Returns whether a placeholder manifest is required for the given format.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * format: pointer to a C string with the mime type or extension.
 *
 * # Returns
 * Returns 1 if a placeholder is required, 0 if not, or -1 on error.
 * Use [`c2pa_error`] to retrieve the error message when -1 is returned.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 */
C2PA_API extern
int c2pa_builder_needs_placeholder(struct C2paBuilder *builder_ptr,
                                   const char *format);

/**
 * Returns the hash binding type that the builder will use for the given format.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * format: pointer to a C string with the MIME type or extension.
 * * out_hash_type: pointer to a C2paHashType that receives the result on success.
 *
 * # Returns
 * 0 on success, -1 on error (null pointer or invalid string).
 *
 * # Safety
 * Reads from NULL-terminated C strings. Writes to `out_hash_type` only on success.
 */
C2PA_API extern
int c2pa_builder_hash_type(struct C2paBuilder *builder_ptr,
                           const char *format,
                           enum C2paHashType *out_hash_type);

/**
 * Creates a composed placeholder manifest from a Builder.
 *
 * The placeholder is a format-specific (e.g. C2PA UUID box for MP4, APP11 for JPEG)
 * byte sequence that can be embedded directly into an asset to reserve space for the
 * final signed manifest.  The placeholder JUMBF length is stored internally in the
 * Builder so that [`c2pa_builder_sign_embeddable`] returns bytes of the identical size.
 *
 * The signer (including its reserve size) is obtained from the Builder's Context.
 * For BMFF assets, if `core.merkle_tree_chunk_size_in_kb` is set in the Context settings,
 * the placeholder will include pre-allocated Merkle map slots for up to 4 mdat boxes.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * format: pointer to a C string with the mime type or extension.
 * * manifest_bytes_ptr: pointer to a pointer to a c_uchar to return the composed placeholder bytes.
 * * (the pointer may be NULL if the caller does not want to receive the bytes)
 *
 * # Errors
 * Returns -1 on error (call c2pa_error() for the message).
 * On success, returns the byte length of the composed placeholder.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned bytes MUST be released by calling c2pa_free.
 */
C2PA_API extern
int64_t c2pa_builder_placeholder(struct C2paBuilder *builder_ptr,
                                 const char *format,
                                 const unsigned char **manifest_bytes_ptr);

/**
 * Signs the manifest and returns composed bytes ready for embedding.
 *
 * Operates in two modes:
 *
 * **Placeholder mode** (after calling [`c2pa_builder_placeholder`]): The Builder knows
 * the pre-committed size of the composed placeholder.  The returned bytes are
 * zero-padded to be exactly the same size, enabling in-place patching of the asset.
 *
 * **Direct mode** (no placeholder): The Builder must already contain a valid hard
 * binding assertion (DataHash, BmffHash, or BoxHash with a real hash value), set
 * either by [`c2pa_builder_update_hash_from_stream`] or directly via the assertion
 * API.  The returned bytes reflect the actual manifest size.
 *
 * The signer is obtained from the Builder's Context.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * format: pointer to a C string with the mime type or extension.
 * * manifest_bytes_ptr: pointer to a pointer to a c_uchar to return the signed manifest bytes.
 *
 * # Errors
 * Returns -1 on error (call c2pa_error() for the message).
 * In direct mode, also returns -1 if no valid hard binding assertion exists.
 * On success, returns the byte length of the signed manifest.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned bytes MUST be released by calling c2pa_free.
 */
C2PA_API extern
int64_t c2pa_builder_sign_embeddable(struct C2paBuilder *builder_ptr,
                                     const char *format,
                                     const unsigned char **manifest_bytes_ptr);

/**
 * Sets the byte exclusion ranges on the DataHash assertion in a Builder.
 *
 * Call this after [`c2pa_builder_placeholder`] to register the exact byte region
 * where the composed placeholder was embedded in the asset.  This step is required
 * before [`c2pa_builder_update_hash_from_stream`] so the hash covers all asset bytes
 * except the manifest slot.
 *
 * Exclusions are provided as a flat array of `(start, length)` pairs, each a `uint64_t`.
 * The layout is: `[start0, length0, start1, length1, …]`, so `exclusions_ptr` must
 * point to `exclusion_count * 2` consecutive `uint64_t` values.
 *
 * The existing DataHash's name and algorithm are preserved; only its exclusion list
 * is replaced.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder (must have called [`c2pa_builder_placeholder`] first).
 * * exclusions_ptr: pointer to a flat array of `(start, length)` uint64_t pairs.
 * * exclusion_count: number of exclusion ranges (not the number of uint64_t values).
 *
 * # Errors
 * Returns 0 on success, -1 on error (call c2pa_error() for the message).
 * Fails if no DataHash assertion exists on the Builder.
 *
 * # Safety
 * `exclusions_ptr` must point to at least `exclusion_count * 2` valid `uint64_t` values.
 */
C2PA_API extern
int c2pa_builder_set_data_hash_exclusions(struct C2paBuilder *builder_ptr,
                                          const uint64_t *exclusions_ptr,
                                          uintptr_t exclusion_count);

/**
 * If set the hasher will hash fixed size chunks of data, padding the final block as needed.
 * This will produce a Merkle tree for each mdat with fixed size leaves, which can be used
 * for efficient hashing of large assets.
 *
 * #Parameters
 * * builder_ptr: pointer to a Builder (must have called [`c2pa_builder_placeholder`] first).
 * * fixed_size_kb: length of fixed size blocks. The units are KB.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * builder_ptr must not be NULL.
 */
C2PA_API extern
int c2pa_builder_set_fixed_size_merkle(struct C2paBuilder *builder_ptr,
                                       uintptr_t fixed_size_kb);

/**
 * Generate the mdat leaf hashes for the asset, the C2paHasher will accumulate the hash values for
 * each mdat_id.  The data_ptr should be supplied in the order the chunks are written to the mdat.
 * The mdat_id should be begin with 0 and increment for each mdat in the asset.  For assets with a s
 * ingle mdat, the mdat_id should be 0.  If fixed size Merkle is enabled, the data will be accumulated
 * and hashed in fixed size chunks and the final chunk will be padded.  Otherwise the data will be hashed
 * as a single leaf for each mdat chunk supplied to this call.
 *
 * #Parameters
 * * builder_ptr: pointer to the C2paBuilder.
 * * mdat_id:  specifies which mdat this hash leaf belongs.
 * * data_ptr: pointer to data to hash.
 * * data_len: length of data to hash.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns 0.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * builder_ptr must not be NULL..
 *
 * # Example
 * ```c
 *  auto data = std::vector<std::uint8_t> buffer(1024);
 *
 *  c2pa_builder_hash_mdat_bytes(builder, 1, (const uint8_t*)data.data(), 1024, true);
 * ```
 */
C2PA_API extern
int c2pa_builder_hash_mdat_bytes(struct C2paBuilder *builder_ptr,
                                 uintptr_t mdat_id,
                                 const unsigned char *data_ptr,
                                 uintptr_t data_len,
                                 bool large_size);

/**
 * Updates the hard binding assertion in a Builder by hashing an asset stream.
 *
 * Automatically detects the type of hard binding on the Builder:
 * - **BmffHash**: uses the assertion's own path-based exclusions (UUID box, mdat when
 *   Merkle hashing is enabled). The hash algorithm is read from the assertion itself.
 * - **BoxHash**: uses the format's box-hash handler to enumerate chunks, hashes each
 *   one individually, and stores the result.  Triggered when a BoxHash assertion is
 *   already present or when `builder.prefer_box_hash` is enabled and the format
 *   supports it.
 * - **DataHash**: reads any exclusion ranges already on the existing DataHash assertion,
 *   hashes the stream excluding those ranges, and stores the result.  If no DataHash
 *   exists, creates one with no exclusions (hashes the entire stream — sidecar case).
 *
 * The hash algorithm is resolved in this order:
 * 1. The `alg` field of the existing hard binding assertion
 * 2. The `alg` field on the ManifestDefinition (set via JSON or builder settings)
 * 3. `"sha256"` (the C2PA default)
 *
 * For DataHash workflows, call [`c2pa_builder_set_data_hash_exclusions`] before this
 * function to register where the composed placeholder was embedded.
 *
 * # Parameters
 * * builder_ptr: pointer to a Builder.
 * * format: MIME type or file extension of the asset (e.g. `"image/jpeg"`).
 * * stream: pointer to a C2paStream of the asset to hash.
 *
 * # Errors
 * Returns 0 on success, -1 on error (call c2pa_error() for the message).
 *
 * # Safety
 * The stream must remain valid for the duration of the call.
 */
C2PA_API extern
int c2pa_builder_update_hash_from_stream(struct C2paBuilder *builder_ptr,
                                         const char *format,
                                         struct C2paStream *stream);

/**
 * Convert a binary c2pa manifest into an embeddable version for the given format.
 * A raw manifest (in application/c2pa format) can be uploaded to the cloud but
 * it cannot be embedded directly into an asset without extra processing.
 * This method converts the raw manifest into an embeddable version that can be
 * embedded into an asset.
 *
 * # Parameters
 * * format: pointer to a C string with the mime type or extension.
 * * manifest_bytes_ptr: pointer to a c_uchar with the raw manifest bytes.
 * * manifest_bytes_size: the size of the manifest_bytes.
 * * result_bytes_ptr: pointer to a pointer to a c_uchar to return the embeddable manifest bytes.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns the size of the result_bytes.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern
int64_t c2pa_format_embeddable(const char *format,
                               const unsigned char *manifest_bytes_ptr,
                               uintptr_t manifest_bytes_size,
                               const unsigned char **result_bytes_ptr);

/**
 * Creates a C2paSigner from a callback and configuration.
 *
 * # Parameters
 * * callback: a callback function to sign data.
 * * alg: the signing algorithm.
 * * certs: a pointer to a NULL-terminated string containing the certificate chain in PEM format.
 * * tsa_url: a pointer to a NULL-terminated string containing the RFC 3161 compliant timestamp authority URL.
 *
 * # Errors
 * Returns NULL if there were errors, otherwise returns a pointer to a C2paSigner.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 * When binding through the C API to other languages, the callback must live long
 * enough, possibly being re-used and called multiple times. The callback is logically
 * owned by the host/caller.
 *
 * # Example
 * ```c
 * auto result = c2pa_signer_create(callback, alg, certs, tsa_url);
 * if (result == NULL) {
 *     auto error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern
struct C2paSigner *c2pa_signer_create(const void *context,
                                      SignerCallback callback,
                                      enum C2paSigningAlg alg,
                                      const char *certs,
                                      const char *tsa_url);

/**
 * Creates a C2paSigner that handles both C2PA claim signing and X.509 identity assertion signing
 * by combining two existing [`C2paSigner`] instances.
 *
 * The resulting signer will embed one X.509 identity assertion (using `cawg.x509.cose`)
 * into every manifest it signs.
 *
 * Both input signers are **consumed** by this call — ownership transfers to the returned
 * signer and the caller MUST NOT free them afterward.
 *
 * # Parameters
 * * `c2pa_signer`: A `C2paSigner` used to sign the C2PA claim. Consumed by this call.
 * * `identity_signer`: A `C2paSigner` used to sign the X.509 identity assertion. Consumed by
 *   this call.
 * * `referenced_assertions`: A NULL-terminated array of NULL-terminated UTF-8 strings naming
 *   assertions to reference in the identity assertion, or NULL if none.
 * * `roles`: A NULL-terminated array of NULL-terminated UTF-8 strings specifying the named
 *   actor's roles, or NULL if none.
 *
 * # Errors
 * Returns NULL if either signer pointer is NULL; call `c2pa_error` to retrieve the error string.
 *
 * # Safety
 * Both signer pointers must have been created by a `c2pa_signer_*` function and not yet freed.
 * After this call they are invalid — do NOT pass them to `c2pa_free`.
 * The returned value MUST be released by calling `c2pa_free`.
 * `referenced_assertions` and `roles`, if non-NULL, must each point to a NULL-terminated array
 * of NULL-terminated UTF-8 strings that remain valid for the duration of this call.
 *
 * # Example
 * ```c
 * C2paSigner* c2pa = c2pa_signer_create(c2pa_ctx, c2pa_sign_cb, C2PA_SIGNING_ALG_ES256, c2pa_certs, NULL);
 * C2paSigner* identity = c2pa_signer_create(id_ctx, id_sign_cb, C2PA_SIGNING_ALG_ES256, id_certs, NULL);
 * const char* refs[] = { "c2pa.actions", NULL };
 * C2paSigner* signer = c2pa_identity_signer_create(c2pa, identity, refs, NULL);
 * if (signer == NULL) {
 *     char* error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern
struct C2paSigner *c2pa_identity_signer_create(struct C2paSigner *c2pa_signer_ptr,
                                               struct C2paSigner *identity_signer_ptr,
                                               const char *const *referenced_assertions,
                                               const char *const *roles);

/**
 * Creates a C2paSigner from a SignerInfo.
 * The signer is created from the sign_cert and private_key fields.
 * an optional url to an RFC 3161 compliant time server will ensure the signature is timestamped.
 *
 * # Parameters
 * * signer_info: pointer to a C2paSignerInfo.
 * # Errors
 * Returns NULL if there were errors, otherwise returns a pointer to a C2paSigner.
 * The error string can be retrieved by calling c2pa_error.
 * # Safety
 * Reads from NULL-terminated C strings.
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 * # Example
 * ```c
 * auto result = c2pa_signer_from_info(signer_info);
 * if (result == NULL) {
 *     auto error = c2pa_error();
 *     printf("Error: %s\n", error);
 *     c2pa_string_free(error);
 * }
 * ```
 */
C2PA_API extern struct C2paSigner *c2pa_signer_from_info(const struct C2paSignerInfo *signer_info);

/**
 * Creates a C2paSigner from the settings.
 * The signer is created from the settings defined in the c2pa_settings.json file.
 *
 * # Errors
 * Returns NULL if there were errors, otherwise returns a pointer to a C2paSigner.
 * The error string can be retrieved by calling c2pa_error.
 * # Safety
 * The returned value MUST be released by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_context_builder_set_signer() to configure a signer on a context instead.")
struct C2paSigner *c2pa_signer_from_settings(void);

/**
 * Returns the size to reserve for the signature for this signer.
 *
 * # Parameters
 * * signer_ptr: pointer to a C2paSigner.
 *
 * # Errors
 * Returns -1 if there were errors, otherwise returns the size to reserve.
 * The error string can be retrieved by calling c2pa_error.
 *
 * # Safety
 * The signer_ptr must be a valid pointer to a C2paSigner.
 */
C2PA_API extern int64_t c2pa_signer_reserve_size(struct C2paSigner *signer_ptr);

/**
 * Frees a C2paSigner allocated by Rust.
 *
 * **Note**: This function is maintained for backward compatibility. New code should
 * use [`c2pa_free`] instead, which works for all pointer types.
 *
 * # Safety
 * The C2paSigner can only be freed once and is invalid after this call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_free() instead, which works for all pointer types.")
void c2pa_signer_free(const struct C2paSigner *signer_ptr);

/**
 * Signs a byte array using the Ed25519 algorithm.
 * # Safety
 * The returned value MUST be freed by calling c2pa_free
 * and it is no longer valid after that call.
 */
C2PA_API extern
const unsigned char *c2pa_ed25519_sign(const unsigned char *bytes,
                                       uintptr_t len,
                                       const char *private_key);

/**
 * Frees a signature allocated by Rust.
 *
 * **Note**: This function is maintained for backward compatibility. New code should
 * use [`c2pa_free`] instead, which works for all pointer types.
 *
 * # Safety
 * The signature can only be freed once and is invalid after this call.
 */
C2PA_API extern
C2PA_DEPRECATED_MSG("Use c2pa_free() instead, which works for all pointer types.")
void c2pa_signature_free(const uint8_t *signature_ptr);

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus
#endif /* C2PA_DYNAMIC_LOADING */

#endif  /* c2pa_bindings_h */

