/**
 * @file
 * @brief "An FFI interface to the pact libraries, enabling cross-language use of Pact's core functionality."
 */


#ifndef pact_ffi_h
#define pact_ffi_h

/* Generated with cbindgen:0.24.3 */

/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */

#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

/**
 * The type of value detected after parsing the expression
 */
enum class ExpressionValueType {
  /**
   * If the type is unknown
   */
  ExpressionValueType_Unknown,
  /**
   * String type
   */
  ExpressionValueType_String,
  /**
   * Numeric type
   */
  ExpressionValueType_Number,
  /**
   * Integer numeric type (no significant figures after the decimal point)
   */
  ExpressionValueType_Integer,
  /**
   * Decimal numeric type (at least one significant figure after the decimal point)
   */
  ExpressionValueType_Decimal,
  /**
   * Boolean type
   */
  ExpressionValueType_Boolean,
};

/**
 * Request or Response enum
 */
enum class InteractionPart {
  /**
   * Request part
   */
  InteractionPart_Request,
  /**
   * Response part
   */
  InteractionPart_Response,
};

/**
 * An enum representing the log level to use.
 *
 * This enum is passed to `log_attach_sink`, which defines where to direct
 * log output at the specified level or lower.
 */
enum class LevelFilter {
  LevelFilter_Off,
  LevelFilter_Error,
  LevelFilter_Warn,
  LevelFilter_Info,
  LevelFilter_Debug,
  LevelFilter_Trace,
};

/**
 * Enum defining the pact specification versions supported by the library
 */
enum class PactSpecification {
  /**
   * Unknown or unsupported specification version
   */
  PactSpecification_Unknown,
  /**
   * First version of the pact specification (<https://github.com/pact-foundation/pact-specification/tree/version-1>)
   */
  PactSpecification_V1,
  /**
   * Second version of the pact specification (<https://github.com/pact-foundation/pact-specification/tree/version-1.1>)
   */
  PactSpecification_V1_1,
  /**
   * Version two of the pact specification (<https://github.com/pact-foundation/pact-specification/tree/version-2>)
   */
  PactSpecification_V2,
  /**
   * Version three of the pact specification (<https://github.com/pact-foundation/pact-specification/tree/version-3>)
   */
  PactSpecification_V3,
  /**
   * Version four of the pact specification (<https://github.com/pact-foundation/pact-specification/tree/version-4>)
   */
  PactSpecification_V4,
};

/**
 * Struct that defines the consumer of the pact.
 */
struct Consumer;

/**
 * Trait to represent a generator
 */
struct Generator;

/**
 * Set of all matching rules
 */
struct MatchingRule;

/**
 * Result of parsing a matching rule definition
 */
struct MatchingRuleDefinitionResult;

/**
 * An iterator over the matching rules from a matching definition expression.
 */
struct MatchingRuleIterator;

/**
 * Struct that defines a message.
 */
struct Message;

/**
 * An iterator that enables FFI iteration over metadata by putting all the keys on the heap
 * and tracking which one we're currently at.
 *
 * This assumes no mutation of the underlying metadata happens while the iterator is live.
 */
struct MessageMetadataIterator;

/**
 * Struct that represents a pact between the consumer and provider of a service.
 * It contains a list of Messages instead of Interactions, but is otherwise
 * identical to `struct Pact`.
 */
struct MessagePact;

/**
 * An iterator over messages in a message pact.
 */
struct MessagePactMessageIterator;

/**
 * An iterator that enables FFI iteration over metadata by putting all the keys on the heap
 * and tracking which one we're currently at.
 *
 * This assumes no mutation of the underlying metadata happens while the iterator is live.
 */
struct MessagePactMetadataIterator;

/**
 * Enum that defines the different types of mismatches that can occur.
 */
struct Mismatch;

/**
 * A collection of mismatches from a matching comparison.
 */
struct Mismatches;

/**
 * An iterator over mismatches.
 */
struct MismatchesIterator;

/**
 * Opaque type for use as a pointer to a Pact model
 */
struct Pact;

/**
 * An iterator over messages in a pact.
 */
struct PactMessageIterator;

/**
 * An iterator over synchronous HTTP request/response interactions in a pact.
 */
struct PactSyncHttpIterator;

/**
 * An iterator over synchronous request/response messages in a pact.
 */
struct PactSyncMessageIterator;

/**
 * Struct that defines a provider of a pact.
 */
struct Provider;

/**
 * Struct that encapsulates all the info about a provider state
 */
struct ProviderState;

/**
 * Iterator over individual provider states.
 */
struct ProviderStateIterator;

/**
 * An iterator that enables FFI iteration over provider state params by putting all the keys on the heap
 * and tracking which one we're currently at.
 *
 * This assumes no mutation of the underlying provider state happens while the iterator is live.
 */
struct ProviderStateParamIterator;

/**
 * V4 HTTP Interaction Type
 */
struct SynchronousHttp;

/**
 * Synchronous interactions as a request message to a sequence of response messages
 */
struct SynchronousMessage;

/**
 * Wraps a Pact verifier
 */
struct VerifierHandle;

/**
 * A single key-value pair exported to the C-side.
 */
struct MessageMetadataPair {
  /**
   * The metadata key.
   */
  const char *key;
  /**
   * The metadata value.
   */
  const char *value;
};

/**
 * A triple, containing the outer key, inner key, and value, exported to the C-side.
 */
struct MessagePactMetadataTriple {
  /**
   * The outer key of the `MessagePact` metadata.
   */
  const char *outer_key;
  /**
   * The inner key of the `MessagePact` metadata.
   */
  const char *inner_key;
  /**
   * The value of the `MessagePact` metadata.
   */
  const char *value;
};

/**
 * A single key-value pair exported to the C-side.
 */
struct ProviderStateParamPair {
  /**
   * The key of the `ProviderState` parameter.
   */
  const char *key;
  /**
   * The value of the `ProviderState` parameter.
   */
  const char *value;
};

/**
 * The matching rule or reference from parsing the matching definition expression.
 *
 * For matching rules, the ID corresponds to the following rules:
 * | Rule | ID |
 * | ---- | -- |
 * | Equality | 1 |
 * | Regex | 2 |
 * | Type | 3 |
 * | MinType | 4 |
 * | MaxType | 5 |
 * | MinMaxType | 6 |
 * | Timestamp | 7 |
 * | Time | 8 |
 * | Date | 9 |
 * | Include | 10 |
 * | Number | 11 |
 * | Integer | 12 |
 * | Decimal | 13 |
 * | Null | 14 |
 * | ContentType | 15 |
 * | ArrayContains | 16 |
 * | Values | 17 |
 * | Boolean | 18 |
 * | StatusCode | 19 |
 * | NotEmpty | 20 |
 * | Semver | 21 |
 * | EachKey | 22 |
 * | EachValue | 23 |
 */
struct MatchingRuleResult {
  enum class Tag {
    /**
     * The matching rule from the expression.
     */
    MatchingRuleResult_MatchingRule,
    /**
     * A reference to a named item.
     */
    MatchingRuleResult_MatchingReference,
  };

  struct MatchingRuleResult_MatchingRule_Body {
    uint16_t _0;
    const char *_1;
    const MatchingRule *_2;
  };

  struct MatchingRuleResult_MatchingReference_Body {
    const char *_0;
  };

  Tag tag;
  union {
    MatchingRuleResult_MatchingRule_Body matching_rule;
    MatchingRuleResult_MatchingReference_Body matching_reference;
  };
};

/**
 * Wraps a Pact model struct
 */
using PactHandle = uint16_t;

/**
 * Result of wrapping a string value
 */
struct StringResult {
  enum class Tag {
    /**
     * Was generated OK
     */
    StringResult_Ok,
    /**
     * There was an error generating the string
     */
    StringResult_Failed,
  };

  struct StringResult_Ok_Body {
    char *_0;
  };

  struct StringResult_Failed_Body {
    char *_0;
  };

  Tag tag;
  union {
    StringResult_Ok_Body ok;
    StringResult_Failed_Body failed;
  };
};

/**
 * Wraps a Pact model struct
 */
using InteractionHandle = uint32_t;

/**
 * Wraps a Pact model struct
 */
using MessagePactHandle = uint16_t;

/**
 * Wraps a Pact model struct
 */
using MessageHandle = uint32_t;

extern "C" {

/**
 * Returns the current library version
 */
const char *pactffi_version();

/**
 * Initialise the mock server library, can provide an environment variable name to use to
 * set the log levels. This function should only be called once, as it tries to install a global
 * tracing subscriber.
 *
 * # Safety
 *
 * log_env_var must be a valid NULL terminated UTF-8 string.
 */
void pactffi_init(const char *log_env_var);

/**
 * Initialises logging, and sets the log level explicitly. This function should only be called
 * once, as it tries to install a global tracing subscriber.
 *
 * # Safety
 *
 * Exported functions are inherently unsafe.
 */
void pactffi_init_with_log_level(const char *level);

/**
 * Enable ANSI coloured output on Windows. On non-Windows platforms, this function is a no-op.
 *
 * # Safety
 *
 * This function is safe.
 */
void pactffi_enable_ansi_support();

/**
 * Log using the shared core logging facility.
 *
 * This is useful for callers to have a single set of logs.
 *
 * * `source` - String. The source of the log, such as the class or caller framework to
 *                      disambiguate log lines from the rust logging (e.g. pact_go)
 * * `log_level` - String. One of TRACE, DEBUG, INFO, WARN, ERROR
 * * `message` - Message to log
 *
 * # Safety
 * This function will fail if any of the pointers passed to it are invalid.
 */
void pactffi_log_message(const char *source, const char *log_level, const char *message);

/**
 * Match a pair of messages, producing a collection of mismatches,
 * which is empty if the two messages matched.
 */
const Mismatches *pactffi_match_message(const Message *msg_1, const Message *msg_2);

/**
 * Get an iterator over mismatches.
 */
MismatchesIterator *pactffi_mismatches_get_iter(const Mismatches *mismatches);

/**
 * Delete mismatches
 */
void pactffi_mismatches_delete(const Mismatches *mismatches);

/**
 * Get the next mismatch from a mismatches iterator.
 *
 * Returns a null pointer if no mismatches remain.
 */
const Mismatch *pactffi_mismatches_iter_next(MismatchesIterator *iter);

/**
 * Delete a mismatches iterator when you're done with it.
 */
void pactffi_mismatches_iter_delete(MismatchesIterator *iter);

/**
 * Get a JSON representation of the mismatch.
 */
const char *pactffi_mismatch_to_json(const Mismatch *mismatch);

/**
 * Get the type of a mismatch.
 */
const char *pactffi_mismatch_type(const Mismatch *mismatch);

/**
 * Get a summary of a mismatch.
 */
const char *pactffi_mismatch_summary(const Mismatch *mismatch);

/**
 * Get a description of a mismatch.
 */
const char *pactffi_mismatch_description(const Mismatch *mismatch);

/**
 * Get an ANSI-compatible description of a mismatch.
 */
const char *pactffi_mismatch_ansi_description(const Mismatch *mismatch);

/**
 * Provide the error message from `LAST_ERROR` to the calling C code.
 *
 * This function should be called after any other function in the pact_matching FFI
 * indicates a failure with its own error message, if the caller wants to get more context
 * on why the error happened.
 *
 * Do note that this error-reporting mechanism only reports the top-level error message,
 * not any source information embedded in the original Rust error type. If you want more
 * detailed information for debugging purposes, use the logging interface.
 *
 * # Params
 *
 * * `buffer`: a pointer to an array of `char` of sufficient length to hold the error message.
 * * `length`: an int providing the length of the `buffer`.
 *
 * # Return Codes
 *
 * * The number of bytes written to the provided buffer, which may be zero if there is no last error.
 * * `-1` if the provided buffer is a null pointer.
 * * `-2` if the provided buffer length is too small for the error message.
 * * `-3` if the write failed for some other reason.
 * * `-4` if the error message had an interior NULL
 *
 * # Notes
 *
 * Note that this function zeroes out any excess in the provided buffer.
 *
 * # Error Handling
 *
 * The return code must be checked for one of the negative number error codes before the buffer
 * is used. If an error code is present, the buffer may not be in a usable state.
 *
 * If the buffer is longer than needed for the error message, the excess space will be zeroed
 * as a safety mechanism. This is slightly less efficient than leaving the contents of the buffer
 * alone, but the difference is expected to be negligible in practice.
 */
int pactffi_get_error_message(char *buffer,
                              int length);

/**
 * Convenience function to direct all logging to stdout.
 */
int pactffi_log_to_stdout(LevelFilter level_filter);

/**
 * Convenience function to direct all logging to stderr.
 */
int pactffi_log_to_stderr(LevelFilter level_filter);

/**
 * Convenience function to direct all logging to a file.
 *
 * # Safety
 * This function will fail if the file_name pointer is invalid or does not point to a NULL
 * terminated string.
 */
int pactffi_log_to_file(const char *file_name, LevelFilter level_filter);

/**
 * Convenience function to direct all logging to a task local memory buffer.
 */
int pactffi_log_to_buffer(LevelFilter level_filter);

/**
 * Initialize the FFI logger with no sinks.
 *
 * This initialized logger does nothing until `pactffi_logger_apply` has been called.
 *
 * # Usage
 *
 * ```c
 * pactffi_logger_init();
 * ```
 *
 * # Safety
 *
 * This function is always safe to call.
 */
void pactffi_logger_init();

/**
 * Attach an additional sink to the thread-local logger.
 *
 * This logger does nothing until `pactffi_logger_apply` has been called.
 *
 * Types of sinks can be specified:
 *
 * - stdout (`pactffi_logger_attach_sink("stdout", LevelFilter_Info)`)
 * - stderr (`pactffi_logger_attach_sink("stderr", LevelFilter_Debug)`)
 * - file w/ file path (`pactffi_logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
 * - buffer (`pactffi_logger_attach_sink("buffer", LevelFilter_Debug)`)
 *
 * # Usage
 *
 * ```c
 * int result = pactffi_logger_attach_sink("file /some/file/path", LogLevel_Filter);
 * ```
 *
 * # Error Handling
 *
 * The return error codes are as follows:
 *
 * - `-1`: Can't set logger (applying the logger failed, perhaps because one is applied already).
 * - `-2`: No logger has been initialized (call `pactffi_logger_init` before any other log function).
 * - `-3`: The sink specifier was not UTF-8 encoded.
 * - `-4`: The sink type specified is not a known type (known types: "stdout", "stderr", or "file /some/path").
 * - `-5`: No file path was specified in a file-type sink specification.
 * - `-6`: Opening a sink to the specified file path failed (check permissions).
 *
 * # Safety
 *
 * This function checks the validity of the passed-in sink specifier, and errors
 * out if the specifier isn't valid UTF-8. Passing in an invalid or NULL pointer will result in
 * undefined behaviour.
 */
int pactffi_logger_attach_sink(const char *sink_specifier,
                               LevelFilter level_filter);

/**
 * Apply the previously configured sinks and levels to the program. If no sinks have been setup,
 * will set the log level to info and the target to standard out.
 *
 * This function will install a global tracing subscriber. Any attempts to modify the logger
 * after the call to `logger_apply` will fail.
 */
int pactffi_logger_apply();

/**
 * Fetch the in-memory logger buffer contents. This will only have any contents if the `buffer`
 * sink has been configured to log to. The contents will be allocated on the heap and will need
 * to be freed with `pactffi_string_delete`.
 *
 * Fetches the logs associated with the provided identifier, or uses the "global" one if the
 * identifier is not specified (i.e. NULL).
 *
 * Returns a NULL pointer if the buffer can't be fetched. This can occur is there is not
 * sufficient memory to make a copy of the contents or the buffer contains non-UTF-8 characters.
 *
 * # Safety
 *
 * This function will fail if the log_id pointer is invalid or does not point to a NULL
 * terminated string.
 */
const char *pactffi_fetch_log_buffer(const char *log_id);

/**
 * Parses the provided JSON into a Pact model. The returned Pact model must be freed with the
 * `pactffi_pact_model_delete` function when no longer needed.
 *
 * # Error Handling
 *
 * This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
 */
Pact *pactffi_parse_pact_json(const char *json);

/**
 * Frees the memory used by the Pact model
 */
void pactffi_pact_model_delete(Pact *pact);

/**
 * Get a copy of this consumer's name.
 *
 * The copy must be deleted with `pactffi_string_delete`.
 *
 * # Usage
 *
 * ```c
 * // Assuming `file_name` and `json_str` are already defined.
 *
 * MessagePact *message_pact = pactffi_message_pact_new_from_json(file_name, json_str);
 * if (message_pact == NULLPTR) {
 *     // handle error.
 * }
 *
 * Consumer *consumer = pactffi_message_pact_get_consumer(message_pact);
 * if (consumer == NULLPTR) {
 *     // handle error.
 * }
 *
 * char *name = pactffi_consumer_get_name(consumer);
 * if (name == NULL) {
 *     // handle error.
 * }
 *
 * printf("%s\n", name);
 *
 * pactffi_string_delete(name);
 * ```
 *
 * # Errors
 *
 * This function will fail if it is passed a NULL pointer,
 * or the Rust string contains an embedded NULL byte.
 * In the case of error, a NULL pointer will be returned.
 */
const char *pactffi_consumer_get_name(const Consumer *consumer);

/**
 * Get a mutable pointer to a newly-created default message on the heap.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * Returns NULL on error.
 */
Message *pactffi_message_new();

/**
 * Constructs a `Message` from the JSON string
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the JSON string is invalid or not UTF-8 encoded, returns a NULL.
 */
Message *pactffi_message_new_from_json(unsigned int index,
                                       const char *json_str,
                                       PactSpecification spec_version);

/**
 * Constructs a `Message` from a body with a given content-type.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the body or content type are invalid or not UTF-8 encoded, returns NULL.
 */
Message *pactffi_message_new_from_body(const char *body, const char *content_type);

/**
 * Destroy the `Message` being pointed to.
 */
void pactffi_message_delete(Message *message);

/**
 * Get the contents of a `Message` in string form.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * The returned string can outlive the message.
 *
 * # Error Handling
 *
 * If the message is NULL, returns NULL. If the body of the message
 * is missing, then this function also returns NULL. This means there's
 * no mechanism to differentiate with this function call alone between
 * a NULL message and a missing message body.
 */
const char *pactffi_message_get_contents(const Message *message);

/**
 * Sets the contents of the message.
 *
 * # Safety
 *
 * The message contents and content type must either be NULL pointers, or point to valid
 * UTF-8 encoded NULL-terminated strings. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the message contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_message_set_contents(Message *message, const char *contents, const char *content_type);

/**
 * Get the length of the contents of a `Message`.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the message is NULL, returns 0. If the body of the message
 * is missing, then this function also returns 0.
 */
size_t pactffi_message_get_contents_length(const Message *message);

/**
 * Get the contents of a `Message` as a pointer to an array of bytes.
 *
 * # Safety
 *
 * The number of bytes in the buffer will be returned by `pactffi_message_get_contents_length`.
 * It is safe to use the pointer while the message is not deleted or changed. Using the pointer
 * after the message is mutated or deleted may lead to undefined behaviour.
 *
 * # Error Handling
 *
 * If the message is NULL, returns NULL. If the body of the message
 * is missing, then this function also returns NULL.
 */
const unsigned char *pactffi_message_get_contents_bin(const Message *message);

/**
 * Sets the contents of the message as an array of bytes.
 *
 * # Safety
 *
 * The contents pointer must be valid for reads of `len` bytes, and it must be properly aligned
 * and consecutive. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the message contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_message_set_contents_bin(Message *message,
                                      const unsigned char *contents,
                                      size_t len,
                                      const char *content_type);

/**
 * Get a copy of the description.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * Since it is a copy, the returned string may safely outlive
 * the `Message`.
 *
 * # Errors
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if the Rust string contains embedded
 * null ('\0') bytes.
 */
const char *pactffi_message_get_description(const Message *message);

/**
 * Write the `description` field on the `Message`.
 *
 * # Safety
 *
 * `description` must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 * This function will only reallocate if the new string
 * does not fit in the existing buffer.
 *
 * # Error Handling
 *
 * Errors will be reported with a non-zero return value.
 */
int pactffi_message_set_description(Message *message, const char *description);

/**
 * Get a copy of the provider state at the given index from this message.
 *
 * # Safety
 *
 * The returned structure must be deleted with `provider_state_delete`.
 *
 * Since it is a copy, the returned structure may safely outlive
 * the `Message`.
 *
 * # Error Handling
 *
 * On failure, this function will return a variant other than Success.
 *
 * This function may fail if the index requested is out of bounds,
 * or if any of the Rust strings contain embedded null ('\0') bytes.
 */
const ProviderState *pactffi_message_get_provider_state(const Message *message, unsigned int index);

/**
 * Get an iterator over provider states.
 *
 * # Safety
 *
 * The underlying data must not change during iteration.
 *
 * # Error Handling
 *
 * Returns NULL if an error occurs.
 */
ProviderStateIterator *pactffi_message_get_provider_state_iter(Message *message);

/**
 * Get the next value from the iterator.
 *
 * # Safety
 *
 * The underlying data must not change during iteration.
 *
 * If a previous call panicked, then the internal mutex will have been poisoned and this
 * function will return NULL.
 *
 * # Error Handling
 *
 * Returns NULL if an error occurs.
 */
ProviderState *pactffi_provider_state_iter_next(ProviderStateIterator *iter);

/**
 * Delete the iterator.
 */
void pactffi_provider_state_iter_delete(ProviderStateIterator *iter);

/**
 * Get a copy of the metadata value indexed by `key`.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * Since it is a copy, the returned string may safely outlive
 * the `Message`.
 *
 * The returned pointer will be NULL if the metadata does not contain
 * the given key, or if an error occurred.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if the provided `key` string contains
 * invalid UTF-8, or if the Rust string contains embedded null ('\0')
 * bytes.
 */
const char *pactffi_message_find_metadata(const Message *message, const char *key);

/**
 * Insert the (`key`, `value`) pair into this Message's
 * `metadata` HashMap.
 *
 * # Safety
 *
 * This function returns an enum indicating the result;
 * see the comments on HashMapInsertStatus for details.
 *
 * # Error Handling
 *
 * This function may fail if the provided `key` or `value` strings
 * contain invalid UTF-8.
 */
int pactffi_message_insert_metadata(Message *message, const char *key, const char *value);

/**
 * Get an iterator over the metadata of a message.
 *
 * # Safety
 *
 * This iterator carries a pointer to the message, and must
 * not outlive the message.
 *
 * The message metadata also must not be modified during iteration. If it is,
 * the old iterator must be deleted and a new iterator created.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if any of the Rust strings contain
 * embedded null ('\0') bytes.
 */
MessageMetadataIterator *pactffi_message_get_metadata_iter(Message *message);

/**
 * Get the next key and value out of the iterator, if possible
 *
 * # Safety
 *
 * The underlying data must not change during iteration.
 *
 * # Error Handling
 *
 * If no further data is present, returns NULL.
 */
MessageMetadataPair *pactffi_message_metadata_iter_next(MessageMetadataIterator *iter);

/**
 * Free the metadata iterator when you're done using it.
 */
void pactffi_message_metadata_iter_delete(MessageMetadataIterator *iter);

/**
 * Free a pair of key and value returned from `message_metadata_iter_next`.
 */
void pactffi_message_metadata_pair_delete(MessageMetadataPair *pair);

/**
 * Construct a new `MessagePact` from the JSON string.
 * The provided file name is used when generating error messages.
 *
 * # Safety
 *
 * The `file_name` and `json_str` parameters must both be valid UTF-8
 * encoded strings.
 *
 * # Error Handling
 *
 * On error, this function will return a null pointer.
 */
MessagePact *pactffi_message_pact_new_from_json(const char *file_name, const char *json_str);

/**
 * Delete the `MessagePact` being pointed to.
 */
void pactffi_message_pact_delete(MessagePact *message_pact);

/**
 * Get a pointer to the Consumer struct inside the MessagePact.
 * This is a mutable borrow: The caller may mutate the Consumer
 * through this pointer.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * This function will only fail if it is passed a NULL pointer.
 * In the case of error, a NULL pointer will be returned.
 */
Consumer *pactffi_message_pact_get_consumer(MessagePact *message_pact);

/**
 * Get a pointer to the Provider struct inside the MessagePact.
 * This is a mutable borrow: The caller may mutate the Provider
 * through this pointer.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * This function will only fail if it is passed a NULL pointer.
 * In the case of error, a NULL pointer will be returned.
 */
Provider *pactffi_message_pact_get_provider(MessagePact *message_pact);

/**
 * Get an iterator over the messages of a message pact.
 *
 * # Safety
 *
 * This iterator carries a pointer to the message pact, and must
 * not outlive the message pact.
 *
 * The message pact messages also must not be modified during iteration.
 * If they are, the old iterator must be deleted and a new iterator created.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if any of the Rust strings contain embedded
 * null ('\0') bytes.
 */
MessagePactMessageIterator *pactffi_message_pact_get_message_iter(MessagePact *message_pact);

/**
 * Get the next message from the message pact.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
 */
Message *pactffi_message_pact_message_iter_next(MessagePactMessageIterator *iter);

/**
 * Delete the iterator.
 */
void pactffi_message_pact_message_iter_delete(MessagePactMessageIterator *iter);

/**
 * Get a copy of the metadata value indexed by `key1` and `key2`.
 *
 * # Safety
 *
 * Since it is a copy, the returned string may safely outlive
 * the `Message`.
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * The returned pointer will be NULL if the metadata does not contain
 * the given key, or if an error occurred.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if the provided `key1` or `key2` strings contains
 * invalid UTF-8, or if the Rust string contains embedded null ('\0')
 * bytes.
 */
const char *pactffi_message_pact_find_metadata(const MessagePact *message_pact,
                                               const char *key1,
                                               const char *key2);

/**
 * Get an iterator over the metadata of a message pact.
 *
 * # Safety
 *
 * This iterator carries a pointer to the message pact, and must
 * not outlive the message pact.
 *
 * The message pact metadata also must not be modified during iteration. If it is,
 * the old iterator must be deleted and a new iterator created.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if any of the Rust strings contain
 * embedded null ('\0') bytes.
 */
MessagePactMetadataIterator *pactffi_message_pact_get_metadata_iter(MessagePact *message_pact);

/**
 * Get the next triple out of the iterator, if possible
 *
 * # Safety
 *
 * This operation is invalid if the underlying data has been changed during iteration.
 *
 * # Error Handling
 *
 * Returns null if no next element is present.
 */
MessagePactMetadataTriple *pactffi_message_pact_metadata_iter_next(MessagePactMetadataIterator *iter);

/**
 * Free the metadata iterator when you're done using it.
 */
void pactffi_message_pact_metadata_iter_delete(MessagePactMetadataIterator *iter);

/**
 * Free a triple returned from `pactffi_message_pact_metadata_iter_next`.
 */
void pactffi_message_pact_metadata_triple_delete(MessagePactMetadataTriple *triple);

/**
 * Get a copy of this provider's name.
 *
 * The copy must be deleted with `pactffi_string_delete`.
 *
 * # Usage
 *
 * ```c
 * // Assuming `file_name` and `json_str` are already defined.
 *
 * MessagePact *message_pact = pactffi_message_pact_new_from_json(file_name, json_str);
 * if (message_pact == NULLPTR) {
 *     // handle error.
 * }
 *
 * Provider *provider = pactffi_message_pact_get_provider(message_pact);
 * if (provider == NULLPTR) {
 *     // handle error.
 * }
 *
 * char *name = pactffi_provider_get_name(provider);
 * if (name == NULL) {
 *     // handle error.
 * }
 *
 * printf("%s\n", name);
 *
 * pactffi_string_delete(name);
 * ```
 *
 * # Errors
 *
 * This function will fail if it is passed a NULL pointer,
 * or the Rust string contains an embedded NULL byte.
 * In the case of error, a NULL pointer will be returned.
 */
const char *pactffi_provider_get_name(const Provider *provider);

/**
 * Get the name of the provider state as a string, which needs to be deleted with `pactffi_string_delete`.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the provider_state param is NULL, this returns NULL.
 */
const char *pactffi_provider_state_get_name(const ProviderState *provider_state);

/**
 * Get an iterator over the params of a provider state.
 *
 * # Safety
 *
 * This iterator carries a pointer to the provider state, and must
 * not outlive the provider state.
 *
 * The provider state params also must not be modified during iteration. If it is,
 * the old iterator must be deleted and a new iterator created.
 *
 * # Errors
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if any of the Rust strings contain
 * embedded null ('\0') bytes.
 */
ProviderStateParamIterator *pactffi_provider_state_get_param_iter(ProviderState *provider_state);

/**
 * Get the next key and value out of the iterator, if possible
 *
 * Returns a pointer to a heap allocated array of 2 elements, the pointer to the
 * key string on the heap, and the pointer to the value string on the heap.
 *
 * # Safety
 *
 * The underlying data must not be modified during iteration.
 *
 * The user needs to free both the contained strings and the array.
 *
 * # Error Handling
 *
 * Returns NULL if there's no further elements or the iterator is NULL.
 */
ProviderStateParamPair *pactffi_provider_state_param_iter_next(ProviderStateParamIterator *iter);

/**
 * Free the provider state when you're done using it.
 */
void pactffi_provider_state_delete(ProviderState *provider_state);

/**
 * Free the provider state param iterator when you're done using it.
 */
void pactffi_provider_state_param_iter_delete(ProviderStateParamIterator *iter);

/**
 * Free a pair of key and value returned from `pactffi_provider_state_param_iter_next`.
 */
void pactffi_provider_state_param_pair_delete(ProviderStateParamPair *pair);

/**
 * Free the iterator when you're done using it.
 */
void pactffi_pact_message_iter_delete(PactMessageIterator *iter);

/**
 * Get the next message from the message pact. As the messages returned are owned by the
 * iterator, they do not need to be deleted but will be cleaned up when the iterator is
 * deleted.
 *
 * Will return a NULL pointer when the iterator has advanced past the end of the list.
 *
 * # Safety
 *
 * This function is safe.
 *
 * Deleting a message returned by the iterator can lead to undefined behaviour.
 *
 * # Error Handling
 *
 * This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
 */
Message *pactffi_pact_message_iter_next(PactMessageIterator *iter);

/**
 * Get the next synchronous request/response message from the pact. As the messages returned are owned by the
 * iterator, they do not need to be deleted but will be cleaned up when the iterator is
 * deleted.
 *
 * Will return a NULL pointer when the iterator has advanced past the end of the list.
 *
 * # Safety
 *
 * This function is safe.
 *
 * Deleting a message returned by the iterator can lead to undefined behaviour.
 *
 * # Error Handling
 *
 * This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
 */
SynchronousMessage *pactffi_pact_sync_message_iter_next(PactSyncMessageIterator *iter);

/**
 * Free the iterator when you're done using it.
 */
void pactffi_pact_sync_message_iter_delete(PactSyncMessageIterator *iter);

/**
 * Get the next synchronous HTTP request/response interaction from the pact. As the
 * interactions returned are owned by the iterator, they do not need to be deleted but
 * will be cleaned up when the iterator is deleted.
 *
 * Will return a NULL pointer when the iterator has advanced past the end of the list.
 *
 * # Safety
 *
 * This function is safe.
 *
 * Deleting an interaction returned by the iterator can lead to undefined behaviour.
 *
 * # Error Handling
 *
 * This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
 */
SynchronousHttp *pactffi_pact_sync_http_iter_next(PactSyncHttpIterator *iter);

/**
 * Free the iterator when you're done using it.
 */
void pactffi_pact_sync_http_iter_delete(PactSyncHttpIterator *iter);

/**
 * Get a mutable pointer to a newly-created default message on the heap.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * Returns NULL on error.
 */
SynchronousMessage *pactffi_sync_message_new();

/**
 * Destroy the `Message` being pointed to.
 */
void pactffi_sync_message_delete(SynchronousMessage *message);

/**
 * Get the request contents of a `SynchronousMessage` in string form.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * The returned string can outlive the message.
 *
 * # Error Handling
 *
 * If the message is NULL, returns NULL. If the body of the request message
 * is missing, then this function also returns NULL. This means there's
 * no mechanism to differentiate with this function call alone between
 * a NULL message and a missing message body.
 */
const char *pactffi_sync_message_get_request_contents(const SynchronousMessage *message);

/**
 * Sets the request contents of the message.
 *
 * * `message` - the message to set the request contents for
 * * `contents` - pointer to contents to copy from. Must be a valid NULL-terminated UTF-8 string pointer.
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The message contents and content type must either be NULL pointers, or point to valid
 * UTF-8 encoded NULL-terminated strings. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the message contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_message_set_request_contents(SynchronousMessage *message,
                                               const char *contents,
                                               const char *content_type);

/**
 * Get the length of the request contents of a `SynchronousMessage`.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the message is NULL, returns 0. If the body of the request
 * is missing, then this function also returns 0.
 */
size_t pactffi_sync_message_get_request_contents_length(const SynchronousMessage *message);

/**
 * Get the request contents of a `SynchronousMessage` as a pointer to an array of bytes.
 *
 * # Safety
 *
 * The number of bytes in the buffer will be returned by `pactffi_sync_message_get_request_contents_length`.
 * It is safe to use the pointer while the message is not deleted or changed. Using the pointer
 * after the message is mutated or deleted may lead to undefined behaviour.
 *
 * # Error Handling
 *
 * If the message is NULL, returns NULL. If the body of the message
 * is missing, then this function also returns NULL.
 */
const unsigned char *pactffi_sync_message_get_request_contents_bin(const SynchronousMessage *message);

/**
 * Sets the request contents of the message as an array of bytes.
 *
 * * `message` - the message to set the request contents for
 * * `contents` - pointer to contents to copy from
 * * `len` - number of bytes to copy from the contents pointer
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The contents pointer must be valid for reads of `len` bytes, and it must be properly aligned
 * and consecutive. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the message contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_message_set_request_contents_bin(SynchronousMessage *message,
                                                   const unsigned char *contents,
                                                   size_t len,
                                                   const char *content_type);

/**
 * Get the number of response messages in the `SynchronousMessage`.
 *
 * # Safety
 *
 * The message pointer must point to a valid SynchronousMessage.
 *
 * # Error Handling
 *
 * If the message is NULL, returns 0.
 */
size_t pactffi_sync_message_get_number_responses(const SynchronousMessage *message);

/**
 * Get the response contents of a `SynchronousMessage` in string form.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * The returned string can outlive the message.
 *
 * # Error Handling
 *
 * If the message is NULL or the index is not valid, returns NULL.
 *
 * If the body of the response message is missing, then this function also returns NULL.
 * This means there's no mechanism to differentiate with this function call alone between
 * a NULL message and a missing message body.
 */
const char *pactffi_sync_message_get_response_contents(const SynchronousMessage *message,
                                                       size_t index);

/**
 * Sets the response contents of the message. If index is greater than the number of responses
 * in the message, the responses will be padded with default values.
 *
 * * `message` - the message to set the response contents for
 * * `index` - index of the response to set. 0 is the first response.
 * * `contents` - pointer to contents to copy from. Must be a valid NULL-terminated UTF-8 string pointer.
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The message contents and content type must either be NULL pointers, or point to valid
 * UTF-8 encoded NULL-terminated strings. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the response contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_message_set_response_contents(SynchronousMessage *message,
                                                size_t index,
                                                const char *contents,
                                                const char *content_type);

/**
 * Get the length of the response contents of a `SynchronousMessage`.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the message is NULL or the index is not valid, returns 0. If the body of the request
 * is missing, then this function also returns 0.
 */
size_t pactffi_sync_message_get_response_contents_length(const SynchronousMessage *message,
                                                         size_t index);

/**
 * Get the response contents of a `SynchronousMessage` as a pointer to an array of bytes.
 *
 * # Safety
 *
 * The number of bytes in the buffer will be returned by `pactffi_sync_message_get_response_contents_length`.
 * It is safe to use the pointer while the message is not deleted or changed. Using the pointer
 * after the message is mutated or deleted may lead to undefined behaviour.
 *
 * # Error Handling
 *
 * If the message is NULL or the index is not valid, returns NULL. If the body of the message
 * is missing, then this function also returns NULL.
 */
const unsigned char *pactffi_sync_message_get_response_contents_bin(const SynchronousMessage *message,
                                                                    size_t index);

/**
 * Sets the response contents of the message at the given index as an array of bytes. If index
 * is greater than the number of responses in the message, the responses will be padded with
 * default values.
 *
 * * `message` - the message to set the response contents for
 * * `index` - index of the response to set. 0 is the first response
 * * `contents` - pointer to contents to copy from
 * * `len` - number of bytes to copy
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The contents pointer must be valid for reads of `len` bytes, and it must be properly aligned
 * and consecutive. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the message contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_message_set_response_contents_bin(SynchronousMessage *message,
                                                    size_t index,
                                                    const unsigned char *contents,
                                                    size_t len,
                                                    const char *content_type);

/**
 * Get a copy of the description.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * Since it is a copy, the returned string may safely outlive
 * the `SynchronousMessage`.
 *
 * # Errors
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if the Rust string contains embedded
 * null ('\0') bytes.
 */
const char *pactffi_sync_message_get_description(const SynchronousMessage *message);

/**
 * Write the `description` field on the `SynchronousMessage`.
 *
 * # Safety
 *
 * `description` must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 * This function will only reallocate if the new string
 * does not fit in the existing buffer.
 *
 * # Error Handling
 *
 * Errors will be reported with a non-zero return value.
 */
int pactffi_sync_message_set_description(SynchronousMessage *message, const char *description);

/**
 * Get a copy of the provider state at the given index from this message.
 *
 * # Safety
 *
 * The returned structure must be deleted with `provider_state_delete`.
 *
 * Since it is a copy, the returned structure may safely outlive
 * the `SynchronousMessage`.
 *
 * # Error Handling
 *
 * On failure, this function will return a variant other than Success.
 *
 * This function may fail if the index requested is out of bounds,
 * or if any of the Rust strings contain embedded null ('\0') bytes.
 */
const ProviderState *pactffi_sync_message_get_provider_state(const SynchronousMessage *message,
                                                             unsigned int index);

/**
 * Get an iterator over provider states.
 *
 * # Safety
 *
 * The underlying data must not change during iteration.
 *
 * # Error Handling
 *
 * Returns NULL if an error occurs.
 */
ProviderStateIterator *pactffi_sync_message_get_provider_state_iter(SynchronousMessage *message);

/**
 * Get a mutable pointer to a newly-created default interaction on the heap.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * Returns NULL on error.
 */
SynchronousHttp *pactffi_sync_http_new();

/**
 * Destroy the `SynchronousHttp` interaction being pointed to.
 */
void pactffi_sync_http_delete(SynchronousHttp *interaction);

/**
 * Get the request contents of a `SynchronousHttp` interaction in string form.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * The returned string can outlive the interaction.
 *
 * # Error Handling
 *
 * If the interaction is NULL, returns NULL. If the body of the request
 * is missing, then this function also returns NULL. This means there's
 * no mechanism to differentiate with this function call alone between
 * a NULL body and a missing body.
 */
const char *pactffi_sync_http_get_request_contents(const SynchronousHttp *interaction);

/**
 * Sets the request contents of the interaction.
 *
 * * `interaction` - the interaction to set the request contents for
 * * `contents` - pointer to contents to copy from. Must be a valid NULL-terminated UTF-8 string pointer.
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The request contents and content type must either be NULL pointers, or point to valid
 * UTF-8 encoded NULL-terminated strings. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the request contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_http_set_request_contents(SynchronousHttp *interaction,
                                            const char *contents,
                                            const char *content_type);

/**
 * Get the length of the request contents of a `SynchronousHttp` interaction.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the interaction is NULL, returns 0. If the body of the request
 * is missing, then this function also returns 0.
 */
size_t pactffi_sync_http_get_request_contents_length(const SynchronousHttp *interaction);

/**
 * Get the request contents of a `SynchronousHttp` interaction as a pointer to an array of bytes.
 *
 * # Safety
 *
 * The number of bytes in the buffer will be returned by `pactffi_sync_http_get_request_contents_length`.
 * It is safe to use the pointer while the interaction is not deleted or changed. Using the pointer
 * after the interaction is mutated or deleted may lead to undefined behaviour.
 *
 * # Error Handling
 *
 * If the interaction is NULL, returns NULL. If the body of the request
 * is missing, then this function also returns NULL.
 */
const unsigned char *pactffi_sync_http_get_request_contents_bin(const SynchronousHttp *interaction);

/**
 * Sets the request contents of the interaction as an array of bytes.
 *
 * * `interaction` - the interaction to set the request contents for
 * * `contents` - pointer to contents to copy from
 * * `len` - number of bytes to copy from the contents pointer
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The contents pointer must be valid for reads of `len` bytes, and it must be properly aligned
 * and consecutive. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the request contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_http_set_request_contents_bin(SynchronousHttp *interaction,
                                                const unsigned char *contents,
                                                size_t len,
                                                const char *content_type);

/**
 * Get the response contents of a `SynchronousHttp` interaction in string form.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * The returned string can outlive the interaction.
 *
 * # Error Handling
 *
 * If the interaction is NULL, returns NULL.
 *
 * If the body of the response is missing, then this function also returns NULL.
 * This means there's no mechanism to differentiate with this function call alone between
 * a NULL body and a missing body.
 */
const char *pactffi_sync_http_get_response_contents(const SynchronousHttp *interaction);

/**
 * Sets the response contents of the interaction.
 *
 * * `interaction` - the interaction to set the response contents for
 * * `contents` - pointer to contents to copy from. Must be a valid NULL-terminated UTF-8 string pointer.
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The response contents and content type must either be NULL pointers, or point to valid
 * UTF-8 encoded NULL-terminated strings. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the response contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_http_set_response_contents(SynchronousHttp *interaction,
                                             const char *contents,
                                             const char *content_type);

/**
 * Get the length of the response contents of a `SynchronousHttp` interaction.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * If the interaction is NULL or the index is not valid, returns 0. If the body of the response
 * is missing, then this function also returns 0.
 */
size_t pactffi_sync_http_get_response_contents_length(const SynchronousHttp *interaction);

/**
 * Get the response contents of a `SynchronousHttp` interaction as a pointer to an array of bytes.
 *
 * # Safety
 *
 * The number of bytes in the buffer will be returned by `pactffi_sync_http_get_response_contents_length`.
 * It is safe to use the pointer while the interaction is not deleted or changed. Using the pointer
 * after the interaction is mutated or deleted may lead to undefined behaviour.
 *
 * # Error Handling
 *
 * If the interaction is NULL, returns NULL. If the body of the response
 * is missing, then this function also returns NULL.
 */
const unsigned char *pactffi_sync_http_get_response_contents_bin(const SynchronousHttp *interaction);

/**
 * Sets the response contents of the `SynchronousHttp` interaction as an array of bytes.
 *
 * * `interaction` - the interaction to set the response contents for
 * * `contents` - pointer to contents to copy from
 * * `len` - number of bytes to copy
 * * `content_type` - pointer to the NULL-terminated UTF-8 string containing the content type of the data.
 *
 * # Safety
 *
 * The contents pointer must be valid for reads of `len` bytes, and it must be properly aligned
 * and consecutive. Otherwise behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the response contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as unknown.
 */
void pactffi_sync_http_set_response_contents_bin(SynchronousHttp *interaction,
                                                 const unsigned char *contents,
                                                 size_t len,
                                                 const char *content_type);

/**
 * Get a copy of the description.
 *
 * # Safety
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * Since it is a copy, the returned string may safely outlive
 * the `SynchronousHttp` interaction.
 *
 * # Errors
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if the Rust string contains embedded
 * null ('\0') bytes.
 */
const char *pactffi_sync_http_get_description(const SynchronousHttp *interaction);

/**
 * Write the `description` field on the `SynchronousHttp`.
 *
 * # Safety
 *
 * `description` must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 * This function will only reallocate if the new string
 * does not fit in the existing buffer.
 *
 * # Error Handling
 *
 * Errors will be reported with a non-zero return value.
 */
int pactffi_sync_http_set_description(SynchronousHttp *interaction, const char *description);

/**
 * Get a copy of the provider state at the given index from this interaction.
 *
 * # Safety
 *
 * The returned structure must be deleted with `provider_state_delete`.
 *
 * Since it is a copy, the returned structure may safely outlive
 * the `SynchronousHttp`.
 *
 * # Error Handling
 *
 * On failure, this function will return a variant other than Success.
 *
 * This function may fail if the index requested is out of bounds,
 * or if any of the Rust strings contain embedded null ('\0') bytes.
 */
const ProviderState *pactffi_sync_http_get_provider_state(const SynchronousHttp *interaction,
                                                          unsigned int index);

/**
 * Get an iterator over provider states.
 *
 * # Safety
 *
 * The underlying data must not change during iteration.
 *
 * # Error Handling
 *
 * Returns NULL if an error occurs.
 */
ProviderStateIterator *pactffi_sync_http_get_provider_state_iter(SynchronousHttp *interaction);

/**
 * Parse a matcher definition string into a MatchingRuleDefinition containing the example value,
 * and matching rules and any generator.
 *
 * The following are examples of matching rule definitions:
 * * `matching(type,'Name')` - type matcher with string value 'Name'
 * * `matching(number,100)` - number matcher
 * * `matching(datetime, 'yyyy-MM-dd','2000-01-01')` - datetime matcher with format string
 *
 * See [Matching Rule definition expressions](https://docs.rs/pact_models/latest/pact_models/matchingrules/expressions/index.html).
 *
 * The returned value needs to be freed up with the `pactffi_matcher_definition_delete` function.
 *
 * # Errors
 * If the expression is invalid, the MatchingRuleDefinition error will be set. You can check for
 * this value with the `pactffi_matcher_definition_error` function.
 *
 * # Safety
 *
 * This function is safe if the expression is a valid NULL terminated string pointer.
 */
const MatchingRuleDefinitionResult *pactffi_parse_matcher_definition(const char *expression);

/**
 * Returns any error message from parsing a matching definition expression. If there is no error,
 * it will return a NULL pointer, otherwise returns the error message as a NULL-terminated string.
 * The returned string must be freed using the `pactffi_string_delete` function once done with it.
 */
const char *pactffi_matcher_definition_error(const MatchingRuleDefinitionResult *definition);

/**
 * Returns the value from parsing a matching definition expression. If there was an error,
 * it will return a NULL pointer, otherwise returns the value as a NULL-terminated string.
 * The returned string must be freed using the `pactffi_string_delete` function once done with it.
 *
 * Note that different expressions values can have types other than a string. Use
 * `pactffi_matcher_definition_value_type` to get the actual type of the value. This function
 * will always return the string representation of the value.
 */
const char *pactffi_matcher_definition_value(const MatchingRuleDefinitionResult *definition);

/**
 * Frees the memory used by the result of parsing the matching definition expression
 */
void pactffi_matcher_definition_delete(const MatchingRuleDefinitionResult *definition);

/**
 * Returns the generator from parsing a matching definition expression. If there was an error or
 * there is no associated generator, it will return a NULL pointer, otherwise returns the generator
 * as a pointer.
 *
 * The generator pointer will be a valid pointer as long as `pactffi_matcher_definition_delete`
 * has not been called on the definition. Using the generator pointer after the definition
 * has been deleted will result in undefined behaviour.
 */
const Generator *pactffi_matcher_definition_generator(const MatchingRuleDefinitionResult *definition);

/**
 * Returns the type of the value from parsing a matching definition expression. If there was an
 * error parsing the expression, it will return Unknown.
 */
ExpressionValueType pactffi_matcher_definition_value_type(const MatchingRuleDefinitionResult *definition);

/**
 * Free the iterator when you're done using it.
 */
void pactffi_matching_rule_iter_delete(MatchingRuleIterator *iter);

/**
 * Returns an iterator over the matching rules from the parsed definition. The iterator needs to
 * be deleted with the `pactffi_matching_rule_iter_delete` function once done with it.
 *
 * If there was an error parsing the expression, this function will return a NULL pointer.
 */
MatchingRuleIterator *pactffi_matcher_definition_iter(const MatchingRuleDefinitionResult *definition);

/**
 * Get the next matching rule or reference from the iterator. As the values returned are owned
 * by the iterator, they do not need to be deleted but will be cleaned up when the iterator is
 * deleted.
 *
 * Will return a NULL pointer when the iterator has advanced past the end of the list.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
 */
const MatchingRuleResult *pactffi_matching_rule_iter_next(MatchingRuleIterator *iter);

/**
 * Get the JSON form of the matching rule.
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * # Safety
 *
 * This function will fail if it is passed a NULL pointer, or the iterator that owns the
 * value of the matching rule has been deleted.
 */
const char *pactffi_matching_rule_to_json(const MatchingRule *rule);

/**
 * Get the JSON form of the generator.
 *
 * The returned string must be deleted with `pactffi_string_delete`.
 *
 * # Safety
 *
 * This function will fail if it is passed a NULL pointer, or the owner of the generator has
 * been deleted.
 */
const char *pactffi_generator_to_json(const Generator *generator);

/**
 * Generate a string value using the provided generator and an optional JSON payload containing
 * any generator context. The context value is used for generators like `MockServerURL` (which
 * should contain details about the running mock server) and `ProviderStateGenerator` (which
 * should be the values returned from the Provider State callback function).
 *
 * If anything goes wrong, it will return a NULL pointer.
 */
const char *pactffi_generator_generate_string(const Generator *generator, const char *context_json);

/**
 * Generate an integer value using the provided generator and an optional JSON payload containing
 * any generator context. The context value is used for generators like `ProviderStateGenerator`
 * (which should be the values returned from the Provider State callback function).
 *
 * If anything goes wrong or the generator is not a type that can generate an integer value, it
 * will return a zero value.
 */
unsigned short pactffi_generator_generate_integer(const Generator *generator,
                                                  const char *context_json);

/**
 * Delete a string previously returned by this FFI.
 *
 * It is explicitly allowed to pass a null pointer to this function;
 * in that case the function will do nothing.
 *
 * # Safety
 * Passing an invalid pointer, or one that was not returned by a FFI function can result in
 * undefined behaviour.
 */
void pactffi_string_delete(char *string);

/**
 * [DEPRECATED] External interface to create a HTTP mock server. A pointer to the pact JSON as a NULL-terminated C
 * string is passed in, as well as the port for the mock server to run on. A value of 0 for the
 * port will result in a port being allocated by the operating system. The port of the mock server is returned.
 *
 * * `pact_str` - Pact JSON
 * * `addr_str` - Address to bind to in the form name:port (i.e. 127.0.0.1:0)
 * * `tls` - boolean flag to indicate of the mock server should use TLS (using a self-signed certificate)
 *
 * This function is deprecated and replaced with `pactffi_create_mock_server_for_transport`.
 *
 * # Errors
 *
 * Errors are returned as negative values.
 *
 * | Error | Description |
 * |-------|-------------|
 * | -1 | A null pointer was received |
 * | -2 | The pact JSON could not be parsed |
 * | -3 | The mock server could not be started |
 * | -4 | The method panicked |
 * | -5 | The address is not valid |
 * | -6 | Could not create the TLS configuration with the self-signed certificate |
 *
 */
int32_t pactffi_create_mock_server(const char *pact_str,
                                   const char *addr_str,
                                   bool tls);

/**
 * Fetch the CA Certificate used to generate the self-signed certificate for the TLS mock server.
 *
 * **NOTE:** The string for the result is allocated on the heap, and will have to be freed
 * by the caller using pactffi_string_delete.
 *
 * # Errors
 *
 * An empty string indicates an error reading the pem file.
 */
char *pactffi_get_tls_ca_certificate();

/**
 * [DEPRECATED] External interface to create a HTTP mock server. A Pact handle is passed in,
 * as well as the port for the mock server to run on. A value of 0 for the port will result in a
 * port being allocated by the operating system. The port of the mock server is returned.
 *
 * * `pact` - Handle to a Pact model created with created with `pactffi_new_pact`.
 * * `addr_str` - Address to bind to in the form name:port (i.e. 127.0.0.1:0). Must be a valid UTF-8 NULL-terminated string.
 * * `tls` - boolean flag to indicate of the mock server should use TLS (using a self-signed certificate)
 *
 * This function is deprecated and replaced with `pactffi_create_mock_server_for_transport`.
 *
 * # Errors
 *
 * Errors are returned as negative values.
 *
 * | Error | Description |
 * |-------|-------------|
 * | -1 | An invalid handle was received. Handles should be created with `pactffi_new_pact` |
 * | -3 | The mock server could not be started |
 * | -4 | The method panicked |
 * | -5 | The address is not valid |
 * | -6 | Could not create the TLS configuration with the self-signed certificate |
 *
 */
int32_t pactffi_create_mock_server_for_pact(PactHandle pact,
                                            const char *addr_str,
                                            bool tls);

/**
 * Create a mock server for the provided Pact handle and transport. If the transport is not
 * provided (it is a NULL pointer or an empty string), will default to an HTTP transport. The
 * address is the interface bind to, and will default to the loopback adapter if not specified.
 * Specifying a value of zero for the port will result in the operating system allocating the port.
 *
 * Parameters:
 * * `pact` - Handle to a Pact model created with created with `pactffi_new_pact`.
 * * `addr` - Address to bind to (i.e. `127.0.0.1` or `[::1]`). Must be a valid UTF-8 NULL-terminated string, or NULL or empty, in which case the loopback adapter is used.
 * * `port` - Port number to bind to. A value of zero will result in the operating system allocating an available port.
 * * `transport` - The transport to use (i.e. http, https, grpc). Must be a valid UTF-8 NULL-terminated string, or NULL or empty, in which case http will be used.
 * * `transport_config` - (OPTIONAL) Configuration for the transport as a valid JSON string. Set to NULL or empty if not required.
 *
 * The port of the mock server is returned.
 *
 * # Safety
 * NULL pointers or empty strings can be passed in for the address, transport and transport_config,
 * in which case a default value will be used. Passing in an invalid pointer will result in undefined behaviour.
 *
 * # Errors
 *
 * Errors are returned as negative values.
 *
 * | Error | Description |
 * |-------|-------------|
 * | -1 | An invalid handle was received. Handles should be created with `pactffi_new_pact` |
 * | -2 | transport_config is not valid JSON |
 * | -3 | The mock server could not be started |
 * | -4 | The method panicked |
 * | -5 | The address is not valid |
 *
 */
int32_t pactffi_create_mock_server_for_transport(PactHandle pact,
                                                 const char *addr,
                                                 uint16_t port,
                                                 const char *transport,
                                                 const char *transport_config);

/**
 * External interface to check if a mock server has matched all its requests. The port number is
 * passed in, and if all requests have been matched, true is returned. False is returned if there
 * is no mock server on the given port, or if any request has not been successfully matched, or
 * the method panics.
 */
bool pactffi_mock_server_matched(int32_t mock_server_port);

/**
 * External interface to get all the mismatches from a mock server. The port number of the mock
 * server is passed in, and a pointer to a C string with the mismatches in JSON format is
 * returned.
 *
 * **NOTE:** The JSON string for the result is allocated on the heap, and will have to be freed
 * once the code using the mock server is complete. The [`cleanup_mock_server`](fn.cleanup_mock_server.html) function is
 * provided for this purpose.
 *
 * # Errors
 *
 * If there is no mock server with the provided port number, or the function panics, a NULL
 * pointer will be returned. Don't try to dereference it, it will not end well for you.
 *
 */
char *pactffi_mock_server_mismatches(int32_t mock_server_port);

/**
 * External interface to cleanup a mock server. This function will try terminate the mock server
 * with the given port number and cleanup any memory allocated for it. Returns true, unless a
 * mock server with the given port number does not exist, or the function panics.
 */
bool pactffi_cleanup_mock_server(int32_t mock_server_port);

/**
 * External interface to trigger a mock server to write out its pact file. This function should
 * be called if all the consumer tests have passed. The directory to write the file to is passed
 * as the second parameter. If a NULL pointer is passed, the current working directory is used.
 *
 * If overwrite is true, the file will be overwritten with the contents of the current pact.
 * Otherwise, it will be merged with any existing pact file.
 *
 * Returns 0 if the pact file was successfully written. Returns a positive code if the file can
 * not be written, or there is no mock server running on that port or the function panics.
 *
 * # Errors
 *
 * Errors are returned as positive values.
 *
 * | Error | Description |
 * |-------|-------------|
 * | 1 | A general panic was caught |
 * | 2 | The pact file was not able to be written |
 * | 3 | A mock server with the provided port was not found |
 */
int32_t pactffi_write_pact_file(int32_t mock_server_port, const char *directory, bool overwrite);

/**
 * Fetch the logs for the mock server. This needs the memory buffer log sink to be setup before
 * the mock server is started. Returned string will be freed with the `cleanup_mock_server`
 * function call.
 *
 * Will return a NULL pointer if the logs for the mock server can not be retrieved.
 */
const char *pactffi_mock_server_logs(int32_t mock_server_port);

/**
 * Generates a datetime value from the provided format string, using the current system date and time
 * NOTE: The memory for the returned string needs to be freed with the `pactffi_string_delete` function
 *
 * # Safety
 *
 * If the format string pointer is NULL or has invalid UTF-8 characters, an error result will be
 * returned. If the format string pointer is not a valid pointer or is not a NULL-terminated string,
 * this will lead to undefined behaviour.
 */
StringResult pactffi_generate_datetime_string(const char *format);

/**
 * Checks that the example string matches the given regex.
 *
 * # Safety
 *
 * Both the regex and example pointers must be valid pointers to NULL-terminated strings. Invalid
 * pointers will result in undefined behaviour.
 */
bool pactffi_check_regex(const char *regex, const char *example);

/**
 * Generates an example string based on the provided regex.
 * NOTE: The memory for the returned string needs to be freed with the `pactffi_string_delete` function.
 *
 * # Safety
 *
 * The regex pointer must be a valid pointer to a NULL-terminated string. Invalid pointers will
 * result in undefined behaviour.
 */
StringResult pactffi_generate_regex_value(const char *regex);

/**
 * [DEPRECATED] Frees the memory allocated to a string by another function
 *
 * This function is deprecated. Use `pactffi_string_delete` instead.
 *
 * # Safety
 *
 * The string pointer can be NULL (which is a no-op), but if it is not a valid pointer the call
 * will result in undefined behaviour.
 */
void pactffi_free_string(char *s);

/**
 * Creates a new Pact model and returns a handle to it.
 *
 * * `consumer_name` - The name of the consumer for the pact.
 * * `provider_name` - The name of the provider for the pact.
 *
 * Returns a new `PactHandle`. The handle will need to be freed with the `pactffi_free_pact_handle`
 * method to release its resources.
 */
PactHandle pactffi_new_pact(const char *consumer_name, const char *provider_name);

/**
 * Creates a new HTTP Interaction and returns a handle to it.
 *
 * * `description` - The interaction description. It needs to be unique for each interaction.
 *
 * Returns a new `InteractionHandle`.
 */
InteractionHandle pactffi_new_interaction(PactHandle pact, const char *description);

/**
 * Creates a new message interaction and return a handle to it
 * * `description` - The interaction description. It needs to be unique for each interaction.
 *
 * Returns a new `InteractionHandle`.
 */
InteractionHandle pactffi_new_message_interaction(PactHandle pact, const char *description);

/**
 * Creates a new synchronous message interaction (request/response) and return a handle to it
 * * `description` - The interaction description. It needs to be unique for each interaction.
 *
 * Returns a new `InteractionHandle`.
 */
InteractionHandle pactffi_new_sync_message_interaction(PactHandle pact, const char *description);

/**
 * Sets the description for the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `description` - The interaction description. It needs to be unique for each interaction.
 */
bool pactffi_upon_receiving(InteractionHandle interaction, const char *description);

/**
 * Adds a provider state to the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `description` - The provider state description. It needs to be unique.
 */
bool pactffi_given(InteractionHandle interaction, const char *description);

/**
 * Sets the test name annotation for the interaction. This allows capturing the name of
 * the test as metadata. This can only be used with V4 interactions.
 *
 * # Safety
 *
 * The test name parameter must be a valid pointer to a NULL terminated string.
 *
 * # Error Handling
 *
 * If the test name can not be set, this will return a positive value.
 *
 * * `1` - Function panicked. Error message will be available by calling `pactffi_get_error_message`.
 * * `2` - Handle was not valid.
 * * `3` - Mock server was already started and the integration can not be modified.
 * * `4` - Not a V4 interaction.
 */
unsigned int pactffi_interaction_test_name(InteractionHandle interaction,
                                           const char *test_name);

/**
 * Adds a provider state to the Interaction with a parameter key and value. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `description` - The provider state description. It needs to be unique.
 * * `name` - Parameter name.
 * * `value` - Parameter value.
 */
bool pactffi_given_with_param(InteractionHandle interaction,
                              const char *description,
                              const char *name,
                              const char *value);

/**
 * Configures the request for the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `method` - The request method. Defaults to GET.
 * * `path` - The request path. Defaults to `/`.
 *
 * To include matching rules for the path (only regex really makes sense to use), include the
 * matching rule JSON format with the value as a single JSON document. I.e.
 *
 * ```c
 * const char* value = "{\"value\":\"/path/to/100\", \"pact:matcher:type\":\"regex\", \"regex\":\"\\/path\\/to\\/\\\\d+\"}";
 * pactffi_with_request(handle, "GET", value);
 * ```
 * See [IntegrationJson.md](https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/IntegrationJson.md)
 */
bool pactffi_with_request(InteractionHandle interaction,
                          const char *method,
                          const char *path);

/**
 * Configures a query parameter for the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `name` - the query parameter name.
 * * `value` - the query parameter value.
 * * `index` - the index of the value (starts at 0). You can use this to create a query parameter with multiple values
 *
 * **DEPRECATED:** Use `pactffi_with_query_parameter_v2`, which deals with multiple values correctly
 */
bool pactffi_with_query_parameter(InteractionHandle interaction,
                                  const char *name,
                                  size_t index,
                                  const char *value);

/**
 * Configures a query parameter for the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `name` - the query parameter name.
 * * `value` - the query parameter value. Either a simple string or a JSON document.
 * * `index` - the index of the value (starts at 0). You can use this to create a query parameter with multiple values
 *
 * To setup a query parameter with multiple values, you can either call this function multiple times
 * with a different index value, i.e. to create `id=2&id=3`
 *
 * ```c
 * pactffi_with_query_parameter_v2(handle, "id", 0, "2");
 * pactffi_with_query_parameter_v2(handle, "id", 1, "3");
 * ```
 *
 * Or you can call it once with a JSON value that contains multiple values:
 *
 * ```c
 * const char* value = "{\"value\": [\"2\",\"3\"]}";
 * pactffi_with_query_parameter_v2(handle, "id", 0, value);
 * ```
 *
 * To include matching rules for the query parameter, include the matching rule JSON format with
 * the value as a single JSON document. I.e.
 *
 * ```c
 * const char* value = "{\"value\":\"2\", \"pact:matcher:type\":\"regex\", \"regex\":\"\\\\d+\"}";
 * pactffi_with_query_parameter_v2(handle, "id", 0, value);
 * ```
 * See [IntegrationJson.md](https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/IntegrationJson.md)
 *
 * # Safety
 * The name and value parameters must be valid pointers to NULL terminated strings.
 * ```
 */
bool pactffi_with_query_parameter_v2(InteractionHandle interaction,
                                     const char *name,
                                     size_t index,
                                     const char *value);

/**
 * Sets the specification version for a given Pact model. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started) or the version is invalid.
 *
 * * `pact` - Handle to a Pact model
 * * `version` - the spec version to use
 */
bool pactffi_with_specification(PactHandle pact,
                                PactSpecification version);

/**
 * Sets the additional metadata on the Pact file. Common uses are to add the client library details such as the name and version
 * Returns false if the interaction or Pact can't be modified (i.e. the mock server for it has already started)
 *
 * * `pact` - Handle to a Pact model
 * * `namespace` - the top level metadat key to set any key values on
 * * `name` - the key to set
 * * `value` - the value to set
 */
bool pactffi_with_pact_metadata(PactHandle pact,
                                const char *namespace_,
                                const char *name,
                                const char *value);

/**
 * Configures a header for the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `part` - The part of the interaction to add the header to (Request or Response).
 * * `name` - the header name.
 * * `value` - the header value.
 * * `index` - the index of the value (starts at 0). You can use this to create a header with multiple values
 *
 * **DEPRECATED:** Use `pactffi_with_header_v2`, which deals with multiple values correctly
 */
bool pactffi_with_header(InteractionHandle interaction,
                         InteractionPart part,
                         const char *name,
                         size_t index,
                         const char *value);

/**
 * Configures a header for the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `part` - The part of the interaction to add the header to (Request or Response).
 * * `name` - the header name.
 * * `value` - the header value.
 * * `index` - the index of the value (starts at 0). You can use this to create a header with multiple values
 *
 * To setup a header with multiple values, you can either call this function multiple times
 * with a different index value, i.e. to create `x-id=2, 3`
 *
 * ```c
 * pactffi_with_header_v2(handle, InteractionPart::Request, "x-id", 0, "2");
 * pactffi_with_header_v2(handle, InteractionPart::Request, "x-id", 1, "3");
 * ```
 *
 * Or you can call it once with a JSON value that contains multiple values:
 *
 * ```c
 * const char* value = "{\"value\": [\"2\",\"3\"]}";
 * pactffi_with_header_v2(handle, InteractionPart::Request, "x-id", 0, value);
 * ```
 *
 * To include matching rules for the header, include the matching rule JSON format with
 * the value as a single JSON document. I.e.
 *
 * ```c
 * const char* value = "{\"value\":\"2\", \"pact:matcher:type\":\"regex\", \"regex\":\"\\\\d+\"}";
 * pactffi_with_header_v2(handle, InteractionPart::Request, "id", 0, value);
 * ```
 * See [IntegrationJson.md](https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/IntegrationJson.md)
 *
 * # Safety
 * The name and value parameters must be valid pointers to NULL terminated strings.
 */
bool pactffi_with_header_v2(InteractionHandle interaction,
                            InteractionPart part,
                            const char *name,
                            size_t index,
                            const char *value);

/**
 * Configures the response for the Interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `status` - the response status. Defaults to 200.
 */
bool pactffi_response_status(InteractionHandle interaction, unsigned short status);

/**
 * Adds the body for the interaction. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `part` - The part of the interaction to add the body to (Request or Response).
 * * `content_type` - The content type of the body. Defaults to `text/plain`. Will be ignored if a content type
 *   header is already set.
 * * `body` - The body contents. For JSON payloads, matching rules can be embedded in the body. See
 * [IntegrationJson.md](https://github.com/pact-foundation/pact-reference/blob/master/rust/pact_ffi/IntegrationJson.md)
 *
 * For HTTP and async message interactions, this will overwrite the body. With asynchronous messages, the
 * part parameter will be ignored. With synchronous messages, the request contents will be overwritten,
 * while a new response will be appended to the message.
 *
 * # Safety
 *
 * The interaction contents and content type must either be NULL pointers, or point to valid
 * UTF-8 encoded NULL-terminated strings. Otherwise, behaviour is undefined.
 *
 * # Error Handling
 *
 * If the contents is a NULL pointer, it will set the body contents as null. If the content
 * type is a null pointer, or can't be parsed, it will set the content type as TEXT.
 * Returns false if the interaction or Pact can't be modified (i.e. the mock server for it has
 * already started) or an error has occurred.
 */
bool pactffi_with_body(InteractionHandle interaction,
                       InteractionPart part,
                       const char *content_type,
                       const char *body);

/**
 * Adds a binary file as the body with the expected content type and example contents. Will use
 * a mime type matcher to match the body. Returns false if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started)
 *
 * * `interaction` - Interaction handle to set the body for.
 * * `part` - Request or response part.
 * * `content_type` - Expected content type.
 * * `body` - example body contents in bytes
 * * `size` - number of bytes in the body
 *
 * For HTTP and async message interactions, this will overwrite the body. With asynchronous messages, the
 * part parameter will be ignored. With synchronous messages, the request contents will be overwritten,
 * while a new response will be appended to the message.
 *
 * # Safety
 *
 * The content type must be a valid UTF-8 encoded NULL-terminated string. The body pointer must
 * be valid for reads of `size` bytes, and it must be properly aligned and consecutive.
 *
 * # Error Handling
 *
 * If the body is a NULL pointer, it will set the body contents as null. If the content
 * type is a null pointer, or can't be parsed, it will return false.
 * Returns false if the interaction or Pact can't be modified (i.e. the mock server for it has
 * already started) or an error has occurred.
 */
bool pactffi_with_binary_file(InteractionHandle interaction,
                              InteractionPart part,
                              const char *content_type,
                              const uint8_t *body,
                              size_t size);

/**
 * Adds a binary file as the body as a MIME multipart with the expected content type and example contents. Will use
 * a mime type matcher to match the body. Returns an error if the interaction or Pact can't be
 * modified (i.e. the mock server for it has already started) or an error occurs.
 *
 * * `interaction` - Interaction handle to set the body for.
 * * `part` - Request or response part.
 * * `content_type` - Expected content type of the file.
 * * `file` - path to the example file
 * * `part_name` - name for the mime part
 *
 * # Safety
 *
 * The content type, file path and part name must be valid pointers to UTF-8 encoded NULL-terminated strings.
 * Passing invalid pointers or pointers to strings that are not NULL terminated will lead to undefined
 * behaviour.
 *
 * # Error Handling
 *
 * If the file path is a NULL pointer, it will set the body contents as as an empty mime-part.
 * If the file path does not point to a valid file, or is not able to be read, it will return an
 * error result. If the content type is a null pointer, or can't be parsed, it will return an error result.
 * Returns an error if the interaction or Pact can't be modified (i.e. the mock server for it has
 * already started), the interaction is not an HTTP interaction or some other error occurs.
 */
StringResult pactffi_with_multipart_file(InteractionHandle interaction,
                                         InteractionPart part,
                                         const char *content_type,
                                         const char *file,
                                         const char *part_name);

/**
 * Get an iterator over all the messages of the Pact. The returned iterator needs to be
 * freed with `pactffi_pact_message_iter_delete`.
 *
 * # Safety
 *
 * The iterator contains a copy of the Pact, so it is always safe to use.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if any of the Rust strings contain embedded
 * null ('\0') bytes.
 */
PactMessageIterator *pactffi_pact_handle_get_message_iter(PactHandle pact);

/**
 * Get an iterator over all the synchronous request/response messages of the Pact.
 * The returned iterator needs to be freed with `pactffi_pact_sync_message_iter_delete`.
 *
 * # Safety
 *
 * The iterator contains a copy of the Pact, so it is always safe to use.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if any of the Rust strings contain embedded
 * null ('\0') bytes.
 */
PactSyncMessageIterator *pactffi_pact_handle_get_sync_message_iter(PactHandle pact);

/**
 * Get an iterator over all the synchronous HTTP request/response interactions of the Pact.
 * The returned iterator needs to be freed with `pactffi_pact_sync_http_iter_delete`.
 *
 * # Safety
 *
 * The iterator contains a copy of the Pact, so it is always safe to use.
 *
 * # Error Handling
 *
 * On failure, this function will return a NULL pointer.
 *
 * This function may fail if any of the Rust strings contain embedded
 * null ('\0') bytes.
 */
PactSyncHttpIterator *pactffi_pact_handle_get_sync_http_iter(PactHandle pact);

/**
 * Creates a new Pact Message model and returns a handle to it.
 *
 * * `consumer_name` - The name of the consumer for the pact.
 * * `provider_name` - The name of the provider for the pact.
 *
 * Returns a new `MessagePactHandle`. The handle will need to be freed with the `pactffi_free_message_pact_handle`
 * function to release its resources.
 */
MessagePactHandle pactffi_new_message_pact(const char *consumer_name,
                                           const char *provider_name);

/**
 * Creates a new Message and returns a handle to it.
 *
 * * `description` - The message description. It needs to be unique for each Message.
 *
 * Returns a new `MessageHandle`.
 */
MessageHandle pactffi_new_message(MessagePactHandle pact, const char *description);

/**
 * Sets the description for the Message.
 *
 * * `description` - The message description. It needs to be unique for each message.
 */
void pactffi_message_expects_to_receive(MessageHandle message, const char *description);

/**
 * Adds a provider state to the Interaction.
 *
 * * `description` - The provider state description. It needs to be unique for each message
 */
void pactffi_message_given(MessageHandle message, const char *description);

/**
 * Adds a provider state to the Message with a parameter key and value.
 *
 * * `description` - The provider state description. It needs to be unique.
 * * `name` - Parameter name.
 * * `value` - Parameter value.
 */
void pactffi_message_given_with_param(MessageHandle message,
                                      const char *description,
                                      const char *name,
                                      const char *value);

/**
 * Adds the contents of the Message.
 *
 * Accepts JSON, binary and other payload types. Binary data will be base64 encoded when serialised.
 *
 * Note: For text bodies (plain text, JSON or XML), you can pass in a C string (NULL terminated)
 * and the size of the body is not required (it will be ignored). For binary bodies, you need to
 * specify the number of bytes in the body.
 *
 * * `content_type` - The content type of the body. Defaults to `text/plain`, supports JSON structures with matchers and binary data.
 * * `body` - The body contents as bytes. For text payloads (JSON, XML, etc.), a C string can be used and matching rules can be embedded in the body.
 * * `content_type` - Expected content type (e.g. application/json, application/octet-stream)
 * * `size` - number of bytes in the message body to read. This is not required for text bodies (JSON, XML, etc.).
 */
void pactffi_message_with_contents(MessageHandle message_handle,
                                   const char *content_type,
                                   const uint8_t *body,
                                   size_t size);

/**
 * Adds expected metadata to the Message
 *
 * * `key` - metadata key
 * * `value` - metadata value.
 */
void pactffi_message_with_metadata(MessageHandle message_handle,
                                   const char *key,
                                   const char *value);

/**
 * Reifies the given message
 *
 * Reification is the process of stripping away any matchers, and returning the original contents.
 * NOTE: the returned string needs to be deallocated with the `free_string` function
 */
const char *pactffi_message_reify(MessageHandle message_handle);

/**
 * External interface to write out the message pact file. This function should
 * be called if all the consumer tests have passed. The directory to write the file to is passed
 * as the second parameter. If a NULL pointer is passed, the current working directory is used.
 *
 * If overwrite is true, the file will be overwritten with the contents of the current pact.
 * Otherwise, it will be merged with any existing pact file.
 *
 * Returns 0 if the pact file was successfully written. Returns a positive code if the file can
 * not be written, or there is no mock server running on that port or the function panics.
 *
 * # Errors
 *
 * Errors are returned as positive values.
 *
 * | Error | Description |
 * |-------|-------------|
 * | 1 | The pact file was not able to be written |
 * | 2 | The message pact for the given handle was not found |
 */
int32_t pactffi_write_message_pact_file(MessagePactHandle pact,
                                        const char *directory,
                                        bool overwrite);

/**
 * Sets the additional metadata on the Pact file. Common uses are to add the client library details such as the name and version
 *
 * * `pact` - Handle to a Pact model
 * * `namespace` - the top level metadat key to set any key values on
 * * `name` - the key to set
 * * `value` - the value to set
 */
void pactffi_with_message_pact_metadata(MessagePactHandle pact,
                                        const char *namespace_,
                                        const char *name,
                                        const char *value);

/**
 * External interface to write out the pact file. This function should
 * be called if all the consumer tests have passed. The directory to write the file to is passed
 * as the second parameter. If a NULL pointer is passed, the current working directory is used.
 *
 * If overwrite is true, the file will be overwritten with the contents of the current pact.
 * Otherwise, it will be merged with any existing pact file.
 *
 * Returns 0 if the pact file was successfully written. Returns a positive code if the file can
 * not be written or the function panics.
 *
 * # Safety
 *
 * The directory parameter must either be NULL or point to a valid NULL terminated string.
 *
 * # Errors
 *
 * Errors are returned as positive values.
 *
 * | Error | Description |
 * |-------|-------------|
 * | 1 | The function panicked. |
 * | 2 | The pact file was not able to be written. |
 * | 3 | The pact for the given handle was not found. |
 */
int32_t pactffi_pact_handle_write_file(PactHandle pact, const char *directory, bool overwrite);

/**
 * Creates a new V4 asynchronous message and returns a handle to it.
 *
 * * `description` - The message description. It needs to be unique for each Message.
 *
 * Returns a new `MessageHandle`.
 */
MessageHandle pactffi_new_async_message(PactHandle pact, const char *description);

/**
 * Delete a Pact handle and free the resources used by it.
 *
 * # Error Handling
 *
 * On failure, this function will return a positive integer value.
 *
 * * `1` - The handle is not valid or does not refer to a valid Pact. Could be that it was previously deleted.
 *
 */
unsigned int pactffi_free_pact_handle(PactHandle pact);

/**
 * Delete a Pact handle and free the resources used by it.
 *
 * # Error Handling
 *
 * On failure, this function will return a positive integer value.
 *
 * * `1` - The handle is not valid or does not refer to a valid Pact. Could be that it was previously deleted.
 *
 */
unsigned int pactffi_free_message_pact_handle(MessagePactHandle pact);

/**
 * External interface to verifier a provider
 *
 * * `args` - the same as the CLI interface, except newline delimited
 *
 * # Errors
 *
 * Errors are returned as non-zero numeric values.
 *
 * | Error | Description |
 * |-------|-------------|
 * | 1 | The verification process failed, see output for errors |
 * | 2 | A null pointer was received |
 * | 3 | The method panicked |
 * | 4 | Invalid arguments were provided to the verification process |
 *
 * # Safety
 *
 * Exported functions are inherently unsafe. Deal.
 */
int32_t pactffi_verify(const char *args);

/**
 * Get a Handle to a newly created verifier. You should call `pactffi_verifier_shutdown` when
 * done with the verifier to free all allocated resources.
 *
 * Deprecated: This function is deprecated. Use `pactffi_verifier_new_for_application` which allows the
 * calling application/framework name and version to be specified.
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * Returns NULL on error.
 */
VerifierHandle *pactffi_verifier_new();

/**
 * Get a Handle to a newly created verifier. You should call `pactffi_verifier_shutdown` when
 * done with the verifier to free all allocated resources
 *
 * # Safety
 *
 * This function is safe.
 *
 * # Error Handling
 *
 * Returns NULL on error.
 */
VerifierHandle *pactffi_verifier_new_for_application(const char *name, const char *version);

/**
 * Shutdown the verifier and release all resources
 */
void pactffi_verifier_shutdown(VerifierHandle *handle);

/**
 * Set the provider details for the Pact verifier. Passing a NULL for any field will
 * use the default value for that field.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_set_provider_info(VerifierHandle *handle,
                                        const char *name,
                                        const char *scheme,
                                        const char *host,
                                        unsigned short port,
                                        const char *path);

/**
 * Adds a new transport for the given provider. Passing a NULL for any field will
 * use the default value for that field.
 *
 * For non-plugin based message interactions, set protocol to "message" and set scheme
 * to an empty string or "https" if secure HTTP is required. Communication to the calling
 * application will be over HTTP to the default provider hostname.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_add_provider_transport(VerifierHandle *handle,
                                             const char *protocol,
                                             unsigned short port,
                                             const char *path,
                                             const char *scheme);

/**
 * Set the filters for the Pact verifier.
 *
 * If `filter_description` is not empty, it needs to be as a regular expression.
 *
 * `filter_no_state` is a boolean value. Set it to greater than zero to turn the option on.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_set_filter_info(VerifierHandle *handle,
                                      const char *filter_description,
                                      const char *filter_state,
                                      unsigned char filter_no_state);

/**
 * Set the provider state URL for the Pact verifier.
 *
 * `teardown` is a boolean value. If teardown state change requests should be made after an
 * interaction is validated (default is false). Set it to greater than zero to turn the
 * option on.
 * `body` is a boolean value. Sets if state change request data should be sent in the body
 * (> 0, true) or as query parameters (== 0, false). Set it to greater than zero to turn the
 * option on.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_set_provider_state(VerifierHandle *handle,
                                         const char *url,
                                         unsigned char teardown,
                                         unsigned char body);

/**
 * Set the options used by the verifier when calling the provider
 *
 * `disable_ssl_verification` is a boolean value. Set it to greater than zero to turn the option on.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
int pactffi_verifier_set_verification_options(VerifierHandle *handle,
                                              unsigned char disable_ssl_verification,
                                              unsigned long request_timeout);

/**
 * Enables or disables coloured output using ANSI escape codes in the verifier output. By default,
 * coloured output is enabled.
 *
 * `coloured_output` is a boolean value. Set it to greater than zero to turn the option on.
 *
 * # Safety
 *
 * This function is safe as long as the handle pointer points to a valid handle.
 *
 */
int pactffi_verifier_set_coloured_output(VerifierHandle *handle, unsigned char coloured_output);

/**
 * Enables or disables if no pacts are found to verify results in an error.
 *
 * `is_error` is a boolean value. Set it to greater than zero to enable an error when no pacts
 * are found to verify, and set it to zero to disable this.
 *
 * # Safety
 *
 * This function is safe as long as the handle pointer points to a valid handle.
 *
 */
int pactffi_verifier_set_no_pacts_is_error(VerifierHandle *handle, unsigned char is_error);

/**
 * Set the options used when publishing verification results to the Pact Broker
 *
 * # Args
 *
 * - `handle` - The pact verifier handle to update
 * - `provider_version` - Version of the provider to publish
 * - `build_url` - URL to the build which ran the verification
 * - `provider_tags` - Collection of tags for the provider
 * - `provider_tags_len` - Number of provider tags supplied
 * - `provider_branch` - Name of the branch used for verification
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
int pactffi_verifier_set_publish_options(VerifierHandle *handle,
                                         const char *provider_version,
                                         const char *build_url,
                                         const char *const *provider_tags,
                                         unsigned short provider_tags_len,
                                         const char *provider_branch);

/**
 * Set the consumer filters for the Pact verifier.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_set_consumer_filters(VerifierHandle *handle,
                                           const char *const *consumer_filters,
                                           unsigned short consumer_filters_len);

/**
 * Adds a custom header to be added to the requests made to the provider.
 *
 * # Safety
 *
 * The header name and value must point to a valid NULL terminated string and must contain
 * valid UTF-8.
 */
void pactffi_verifier_add_custom_header(VerifierHandle *handle,
                                        const char *header_name,
                                        const char *header_value);

/**
 * Adds a Pact file as a source to verify.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_add_file_source(VerifierHandle *handle, const char *file);

/**
 * Adds a Pact directory as a source to verify. All pacts from the directory that match the
 * provider name will be verified.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_add_directory_source(VerifierHandle *handle, const char *directory);

/**
 * Adds a URL as a source to verify. The Pact file will be fetched from the URL.
 *
 * If a username and password is given, then basic authentication will be used when fetching
 * the pact file. If a token is provided, then bearer token authentication will be used.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_url_source(VerifierHandle *handle,
                                 const char *url,
                                 const char *username,
                                 const char *password,
                                 const char *token);

/**
 * Adds a Pact broker as a source to verify. This will fetch all the pact files from the broker
 * that match the provider name.
 *
 * If a username and password is given, then basic authentication will be used when fetching
 * the pact file. If a token is provided, then bearer token authentication will be used.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_broker_source(VerifierHandle *handle,
                                    const char *url,
                                    const char *username,
                                    const char *password,
                                    const char *token);

/**
 * Adds a Pact broker as a source to verify. This will fetch all the pact files from the broker
 * that match the provider name and the consumer version selectors
 * (See `https://docs.pact.io/pact_broker/advanced_topics/consumer_version_selectors/`).
 *
 * The consumer version selectors must be passed in in JSON format.
 *
 * `enable_pending` is a boolean value. Set it to greater than zero to turn the option on.
 *
 * If the `include_wip_pacts_since` option is provided, it needs to be a date formatted in
 * ISO format (YYYY-MM-DD).
 *
 * If a username and password is given, then basic authentication will be used when fetching
 * the pact file. If a token is provided, then bearer token authentication will be used.
 *
 * # Safety
 *
 * All string fields must contain valid UTF-8. Invalid UTF-8
 * will be replaced with U+FFFD REPLACEMENT CHARACTER.
 *
 */
void pactffi_verifier_broker_source_with_selectors(VerifierHandle *handle,
                                                   const char *url,
                                                   const char *username,
                                                   const char *password,
                                                   const char *token,
                                                   unsigned char enable_pending,
                                                   const char *include_wip_pacts_since,
                                                   const char *const *provider_tags,
                                                   unsigned short provider_tags_len,
                                                   const char *provider_branch,
                                                   const char *const *consumer_version_selectors,
                                                   unsigned short consumer_version_selectors_len,
                                                   const char *const *consumer_version_tags,
                                                   unsigned short consumer_version_tags_len);

/**
 * Runs the verification.
 *
 * # Error Handling
 *
 * Errors will be reported with a non-zero return value.
 */
int pactffi_verifier_execute(VerifierHandle *handle);

/**
 * External interface to retrieve the options and arguments available when calling the CLI interface,
 * returning them as a JSON string.
 *
 * The purpose is to then be able to use in other languages which wrap the FFI library, to implement
 * the same CLI functionality automatically without manual maintenance of arguments, help descriptions
 * etc.
 *
 * # Example structure
 * ```json
 * {
 *   "options": [
 *     {
 *       "long": "scheme",
 *       "help": "Provider URI scheme (defaults to http)",
 *       "possible_values": [
 *         "http",
 *         "https"
 *       ],
 *       "default_value": "http"
 *       "multiple": false,
 *     },
 *     {
 *       "long": "file",
 *       "short": "f",
 *       "help": "Pact file to verify (can be repeated)",
 *       "multiple": true
 *     },
 *     {
 *       "long": "user",
 *       "help": "Username to use when fetching pacts from URLS",
 *       "multiple": false,
 *       "env": "PACT_BROKER_USERNAME"
 *     }
 *   ],
 *   "flags": [
 *     {
 *       "long": "disable-ssl-verification",
 *       "help": "Disables validation of SSL certificates",
 *       "multiple": false
 *     }
 *   ]
 * }
 * ```
 *
 * # Safety
 *
 * Exported functions are inherently unsafe.
 */
const char *pactffi_verifier_cli_args();

/**
 * Extracts the logs for the verification run. This needs the memory buffer log sink to be
 * setup before the verification is executed. The returned string will need to be freed with
 * the `free_string` function call to avoid leaking memory.
 *
 * Will return a NULL pointer if the logs for the verification can not be retrieved.
 */
const char *pactffi_verifier_logs(const VerifierHandle *handle);

/**
 * Extracts the logs for the verification run for the provider name. This needs the memory
 * buffer log sink to be setup before the verification is executed. The returned string will
 * need to be freed with the `free_string` function call to avoid leaking memory.
 *
 * Will return a NULL pointer if the logs for the verification can not be retrieved.
 */
const char *pactffi_verifier_logs_for_provider(const char *provider_name);

/**
 * Extracts the standard output for the verification run. The returned string will need to be
 * freed with the `free_string` function call to avoid leaking memory.
 *
 * * `strip_ansi` - This parameter controls ANSI escape codes. Setting it to a non-zero value
 * will cause the ANSI control codes to be stripped from the output.
 *
 * Will return a NULL pointer if the handle is invalid.
 */
const char *pactffi_verifier_output(const VerifierHandle *handle, unsigned char strip_ansi);

/**
 * Extracts the verification result as a JSON document. The returned string will need to be
 * freed with the `free_string` function call to avoid leaking memory.
 *
 * Will return a NULL pointer if the handle is invalid.
 */
const char *pactffi_verifier_json(const VerifierHandle *handle);

/**
 * Add a plugin to be used by the test. The plugin needs to be installed correctly for this
 * function to work.
 *
 * * `plugin_name` is the name of the plugin to load.
 * * `plugin_version` is the version of the plugin to load. It is optional, and can be NULL.
 *
 * Returns zero on success, and a positive integer value on failure.
 *
 * Note that plugins run as separate processes, so will need to be cleaned up afterwards by
 * calling `pactffi_cleanup_plugins` otherwise you will have plugin processes left running.
 *
 * # Safety
 *
 * `plugin_name` must be a valid pointer to a NULL terminated string. `plugin_version` may be null,
 * and if not NULL must also be a valid pointer to a NULL terminated string. Invalid
 * pointers will result in undefined behaviour.
 *
 * # Errors
 *
 * * `1` - A general panic was caught.
 * * `2` - Failed to load the plugin.
 * * `3` - Pact Handle is not valid.
 *
 * When an error errors, LAST_ERROR will contain the error message.
 */
unsigned int pactffi_using_plugin(PactHandle pact,
                                  const char *plugin_name,
                                  const char *plugin_version);

/**
 * Decrement the access count on any plugins that are loaded for the Pact. This will shutdown
 * any plugins that are no longer required (access count is zero).
 */
void pactffi_cleanup_plugins(PactHandle pact);

/**
 * Setup the interaction part using a plugin. The contents is a JSON string that will be passed on to
 * the plugin to configure the interaction part. Refer to the plugin documentation on the format
 * of the JSON contents.
 *
 * Returns zero on success, and a positive integer value on failure.
 *
 * * `interaction` - Handle to the interaction to configure.
 * * `part` - The part of the interaction to configure (request or response). It is ignored for messages.
 * * `content_type` - NULL terminated C string of the content type of the part.
 * * `contents` - NULL terminated C string of the JSON contents that gets passed to the plugin.
 *
 * # Safety
 *
 * `content_type` and `contents` must be a valid pointers to NULL terminated strings. Invalid
 * pointers will result in undefined behaviour.
 *
 * # Errors
 *
 * * `1` - A general panic was caught.
 * * `2` - The mock server has already been started.
 * * `3` - The interaction handle is invalid.
 * * `4` - The content type is not valid.
 * * `5` - The contents JSON is not valid JSON.
 * * `6` - The plugin returned an error.
 *
 * When an error errors, LAST_ERROR will contain the error message.
 */
unsigned int pactffi_interaction_contents(InteractionHandle interaction,
                                          InteractionPart part,
                                          const char *content_type,
                                          const char *contents);

} // extern "C"

#endif // pact_ffi_h
