/*
 Copyright 2023 Google LLC
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

// clang-format off


#pragma once

/* Generated with cbindgen:0.27.0 */

/*
 WARNING: this file is autogenerated by cbindgen. Don't modify this manually.
 Additionally, you should _not_ rely upon the layouts of the generated
 structs and unions if you want your code to be forward-compatible,
 unless a given type explicitly states in its documentation that it has
 a guaranteed forward-compatible layout.
 Instead, you should use _only_ the provided exported function symbols.
*/

#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
#include "np_cpp_ffi_types.h"

namespace np_ffi {
namespace internal {

extern "C" {

/// Overrides the global panic handler to be used when NP C FFI calls panic.
/// This method will only have an effect on the global panic-handler
/// the first time it's called, and this method will return `true`
/// to indicate that the panic handler was successfully set.
/// All subsequent calls to this method
/// will simply ignore the argument and return `false`.
///
/// If the passed function pointer is non-null,
/// then we will call it upon every panic,
/// followed by the default panicking behavior for
/// the platform (in the case where the user-specified
/// function does not terminate or hang the running process.)
///
/// Otherwise, we will resort to the
/// default panicking behavior for the system, which
/// is a printed stack trace followed by an abort
/// when this crate is compiled with `std`,
/// but a bare `loop { }` when this crate is compiled without.
bool np_ffi_global_config_panic_handler(void (*handler)(PanicReason));

/// Checks the current count of all outstanding handle allocations, useful for debugging,
/// logging, and testing
CurrentHandleAllocations np_ffi_global_config_get_current_allocation_count();

/// Sets an override to the number of shards to employ in the NP FFI's
/// internal handle-maps, which places an upper bound on the number
/// of writing threads which may make progress at any one time
/// when concurrently accessing handles of the same type.
///
/// By default, this value will be set to 16, or in `std` environments,
/// the minimum of 16 and the number of available hardware threads.
/// A shard value override of zero will be interpreted the same
/// as this default.
///
/// Setting this value will have no effect if the handle-maps for the
/// API have already begun being used by the client code, and any
/// values set will take effect upon the first usage of _any_ non-`np_ffi_global_config_set`
/// API call.
void np_ffi_global_config_set_num_shards(uint8_t num_shards);

/// Allocates a new credential-book from the given slab, returning a handle
/// to the created object. The slab will be deallocated by this call.
CreateCredentialBookResult np_ffi_create_credential_book_from_slab(CredentialSlab slab);

/// Gets the tag of a `CreateCredentialBookResult` tagged enum.
CreateCredentialBookResultKind np_ffi_CreateCredentialBookResult_kind(CreateCredentialBookResult result);

/// Casts a `CreateCredentialBookResult` to the `SUCCESS` variant, panicking in the
/// case where the passed value is of a different enum variant.
CredentialBook np_ffi_CreateCredentialBookResult_into_SUCCESS(CreateCredentialBookResult result);

/// Deallocates a credential-slab by its handle.
DeallocateResult np_ffi_deallocate_credential_slab(CredentialSlab credential_slab);

/// Deallocates a credential-book by its handle
DeallocateResult np_ffi_deallocate_credential_book(CredentialBook credential_book);

/// Allocates a new credential-slab, returning a handle to the created object
CredentialSlab np_ffi_create_credential_slab();

/// Adds the given V0 discovery credential with some associated
/// match-data to this credential slab.
///
/// Safety: this is safe if the provided pointer points to a valid memory address
/// which contains the correct len amount of bytes. The copy from the memory address isn't atomic,
/// so concurrent modification of the array from another thread would cause undefined behavior.
AddV0CredentialToSlabResult np_ffi_CredentialSlab_add_v0_credential(CredentialSlab credential_slab,
                                                                    V0MatchableCredential v0_cred);

/// Adds the given V1 discovery credential with some associated
/// match-data to this credential slab.
///
/// Safety: this is safe if the provided pointer points to a valid memory address
/// which contains the correct len amount of bytes. The copy from the memory address isn't atomic,
/// so concurrent modification of the array from another thread would cause undefined behavior.
AddV1CredentialToSlabResult np_ffi_CredentialSlab_add_v1_credential(CredentialSlab credential_slab,
                                                                    V1MatchableCredential v1_cred);

/// Frees the underlying resources of the decrypted metadata buffer
DeallocateResult np_ffi_deallocate_DecryptedMetadata(DecryptedMetadata metadata);

/// Gets the tag of a `DecryptMetadataResult` tagged-union. On success the wrapped identity
/// details may be obtained via `DecryptMetadataResult#into_success`.
DecryptMetadataResultKind np_ffi_DecryptMetadataResult_kind(DecryptMetadataResult result);

/// Casts a `DecryptMetadataResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
DecryptedMetadata np_ffi_DecryptMetadataResult_into_SUCCESS(DecryptMetadataResult result);

/// Gets the pointer and length of the heap allocated byte buffer of decrypted metadata
GetMetadataBufferPartsResult np_ffi_DecryptedMetadata_get_metadata_buffer_parts(DecryptedMetadata metadata);

/// Gets the tag of a `GetMetadataBufferPartsResult` tagged-union. On success the wrapped identity
/// details may be obtained via `GetMetadataBufferPartsResult#into_success`.
GetMetadataBufferPartsResultKind np_ffi_GetMetadataBufferPartsResult_kind(GetMetadataBufferPartsResult result);

/// Casts a `GetMetadataBufferPartsResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant. This returns the pointer and length
/// of the byte buffer containing the decrypted metadata.  There can be a data-race between attempts
/// to access the contents of the buffer and attempts to free the handle from different threads.
MetadataBufferParts np_ffi_GetMetadataBufferPartsResult_into_SUCCESS(GetMetadataBufferPartsResult result);

/// Attempts to deserialize an advertisement with the given service-data
/// payload (presumed to be under the NP service UUID) using credentials
/// pulled from the given credential-book.
DeserializeAdvertisementResult np_ffi_deserialize_advertisement(RawAdvertisementPayload adv_payload,
                                                                CredentialBook credential_book);

/// Gets the tag of a `DeserializeAdvertisementResult` tagged-union.
DeserializeAdvertisementResultKind np_ffi_DeserializeAdvertisementResult_kind(DeserializeAdvertisementResult result);

/// Casts a `DeserializeAdvertisementResult` to the `V0` variant, panicking in the
/// case where the passed value is of a different enum variant.
DeserializedV0Advertisement np_ffi_DeserializeAdvertisementResult_into_V0(DeserializeAdvertisementResult result);

/// Casts a `DeserializeAdvertisementResult` to the `V1` variant, panicking in the
/// case where the passed value is of a different enum variant.
DeserializedV1Advertisement np_ffi_DeserializeAdvertisementResult_into_V1(DeserializeAdvertisementResult result);

/// Deallocates any internal data referenced by a `DeserializeAdvertisementResult`. This should only
/// be used if into_V0 or into_V1, have not been called yet as it shares the same underlying
/// resource.
DeallocateResult np_ffi_deallocate_deserialize_advertisement_result(DeserializeAdvertisementResult result);

/// Deallocates any internal data referenced by a `DeserializedV0Advertisement`
DeallocateResult np_ffi_deallocate_deserialized_V0_advertisement(DeserializedV0Advertisement adv);

/// Deallocates any internal data referenced by a `DeserializedV1Advertisement`
DeallocateResult np_ffi_deallocate_deserialized_V1_advertisement(DeserializedV1Advertisement adv);

/// Gets the tag of a `DeserializedV0Advertisement` tagged-union.
DeserializedV0AdvertisementKind np_ffi_DeserializedV0Advertisement_kind(DeserializedV0Advertisement result);

/// Casts a `DeserializedV0Advertisement` to the `Legible` variant, panicking in the
/// case where the passed value is of a different enum variant.
LegibleDeserializedV0Advertisement np_ffi_DeserializedV0Advertisement_into_LEGIBLE(DeserializedV0Advertisement adv);

/// Gets the number of DEs in a legible deserialized advertisement.
/// Suitable as an iteration bound for `V0Payload#get_de`.
uint8_t np_ffi_LegibleDeserializedV0Advertisement_get_num_des(LegibleDeserializedV0Advertisement adv);

/// Gets just the data-element payload of a `LegibleDeserializedV0Advertisement`.
V0Payload np_ffi_LegibleDeserializedV0Advertisement_into_payload(LegibleDeserializedV0Advertisement adv);

/// Gets just the identity kind associated with a `LegibleDeserializedV0Advertisement`.
DeserializedV0IdentityKind np_ffi_LegibleDeserializedV0Advertisement_get_identity_kind(LegibleDeserializedV0Advertisement adv);

/// Deallocates any internal data of a `LegibleDeserializedV0Advertisement`
DeallocateResult np_ffi_deallocate_legible_v0_advertisement(LegibleDeserializedV0Advertisement adv);

/// Attempts to get the data-element with the given index in the passed v0 adv payload
GetV0DEResult np_ffi_V0Payload_get_de(V0Payload payload, uint8_t index);

/// Attempts to decrypt the metadata for the matched credential for this V0 payload (if any)
DecryptMetadataResult np_ffi_V0Payload_decrypt_metadata(V0Payload payload);

/// Gets the identity details for this V0 payload, or returns an error if this payload does not have
/// any associated identity (public advertisement)
GetV0IdentityDetailsResult np_ffi_V0Payload_get_identity_details(V0Payload payload);

/// Gets the tag of a `GetV0IdentityDetailsResult` tagged-union. On success the wrapped identity
/// details may be obtained via `GetV0IdentityDetailsResult#into_success`.
GetV0IdentityDetailsResultKind np_ffi_GetV0IdentityDetailsResult_kind(GetV0IdentityDetailsResult result);

/// Casts a `GetV0IdentityDetailsResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
DeserializedV0IdentityDetails np_ffi_GetV0IdentityDetailsResult_into_SUCCESS(GetV0IdentityDetailsResult result);

/// Deallocates any internal data of a `V0Payload`
DeallocateResult np_ffi_deallocate_v0_payload(V0Payload payload);

/// Gets the tag of a `GetV0DEResult` tagged-union.
GetV0DEResultKind np_ffi_GetV0DEResult_kind(GetV0DEResult result);

/// Casts a `GetV0DEResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
V0DataElement np_ffi_GetV0DEResult_into_SUCCESS(GetV0DEResult result);

/// Gets the number of legible sections on a deserialized V1 advertisement.
/// Suitable as an index bound for the second argument of
/// `np_ffi_DeserializedV1Advertisement#get_section`.
uint8_t np_ffi_DeserializedV1Advertisement_get_num_legible_sections(DeserializedV1Advertisement adv);

/// Gets the number of sections on a deserialized V1 advertisement which
/// were unable to be decrypted with the credentials that the receiver possesses.
uint8_t np_ffi_DeserializedV1Advertisement_get_num_undecryptable_sections(DeserializedV1Advertisement adv);

/// Gets the legible section with the given index in a deserialized V1 advertisement.
GetV1SectionResult np_ffi_DeserializedV1Advertisement_get_section(DeserializedV1Advertisement adv,
                                                                  uint8_t legible_section_index);

/// Gets the tag of the `GetV1SectionResult` tagged-union.
GetV1SectionResultKind np_ffi_GetV1SectionResult_kind(GetV1SectionResult result);

/// Casts a `GetV1SectionResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
DeserializedV1Section np_ffi_GetV1SectionResult_into_SUCCESS(GetV1SectionResult result);

/// Gets the number of data elements in a deserialized v1 section.
/// Suitable as an iteration bound for the second argument of
/// `np_ffi_DeserializedV1Section_get_de`.
uint8_t np_ffi_DeserializedV1Section_get_num_des(DeserializedV1Section section);

/// Gets the tag of the identity tagged-union used for the passed section.
DeserializedV1IdentityKind np_ffi_DeserializedV1Section_get_identity_kind(DeserializedV1Section section);

/// Gets the data-element with the given index in the passed section.
GetV1DEResult np_ffi_DeserializedV1Section_get_de(DeserializedV1Section section, uint8_t de_index);

/// Gets the identity details used to decrypt this V1 section, or returns an error if this payload
/// does not have any associated identity (public advertisement)
GetV1IdentityDetailsResult np_ffi_DeserializedV1Section_get_identity_details(DeserializedV1Section section);

/// Gets the tag of a `GetV1IdentityDetailsResult` tagged-union. On success the wrapped identity
/// details may be obtained via `GetV0IdentityDetailsResult#into_success`.
GetV1IdentityDetailsResultKind np_ffi_GetV1IdentityDetailsResult_kind(GetV1IdentityDetailsResult result);

/// Casts a `GetV1IdentityDetailsResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
DeserializedV1IdentityDetails np_ffi_GetV1IdentityDetailsResult_into_SUCCESS(GetV1IdentityDetailsResult result);

/// Attempts to decrypt the metadata for the matched credential for this V0 payload (if any)
DecryptMetadataResult np_ffi_DeserializedV1Section_decrypt_metadata(DeserializedV1Section section);

/// Attempts to derive a 16-byte DE salt for a DE with the given type-code in this
/// section. This operation may fail if the passed type-code is forbidden (0xFFFFFFFF)
/// or if the section is leveraging a public identity, and hence, doesn't have an associated salt.
GetV1DE16ByteSaltResult np_ffi_DeserializedV1Section_derive_16_byte_salt_for_de_type(DeserializedV1Section section,
                                                                                     V1DEType de_type);

/// Gets the tag of a `GetV1DE16ByteSaltResult` tagged-union. On success the wrapped identity
/// details may be obtained via `GetV1DE16ByteSaltResult#into_success`.
GetV1DE16ByteSaltResultKind np_ffi_GetV1DE16ByteSaltResult_kind(GetV1DE16ByteSaltResult result);

/// Casts a `GetV1DE16ByteSaltResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
FixedSizeArray<16> np_ffi_GetV1DE16ByteSaltResult_into_SUCCESS(GetV1DE16ByteSaltResult result);

/// Gets the tag of the `GetV1DEResult` tagged-union.
GetV1DEResultKind np_ffi_GetV1DEResult_kind(GetV1DEResult result);

/// Casts a `GetV1DEResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
GenericV1DataElement np_ffi_GetV1DEResult_into_SUCCESS(GetV1DEResult result);

/// Attempts to add the given data element to the V0
/// advertisement builder behind the passed handle.
///
/// This method may invoke the panic handler if the passed DE
/// has an invalid layout, which may indicate that the backing
/// data on the stack was somehow tampered with in an unintended way.
AddV0DEResult np_ffi_V0AdvertisementBuilder_add_de(V0AdvertisementBuilder adv_builder,
                                                   V0DataElement de);

/// Attempts to serialize the contents of the advertisement builder
/// behind this handle to bytes. Assuming that the handle is valid,
/// this operation will always result in the contents behind the
/// advertisement builder handle being deallocated.
SerializeV0AdvertisementResult np_ffi_V0AdvertisementBuilder_into_advertisement(V0AdvertisementBuilder adv_builder);

/// Attempts to deallocate the v0 advertisement builder behind
/// the given handle.
DeallocateResult np_ffi_deallocate_v0_advertisement_builder(V0AdvertisementBuilder adv_builder);

/// Creates a new V0 advertisement builder for a public advertisement.
V0AdvertisementBuilder np_ffi_create_v0_public_advertisement_builder();

/// Creates a new V0 advertisement builder for an encrypted advertisement.
V0AdvertisementBuilder np_ffi_create_v0_encrypted_advertisement_builder(V0BroadcastCredential broadcast_cred,
                                                                        FixedSizeArray<2> salt);

/// Gets the tag of a `SerializeV0AdvertisementResult` tagged-union.
SerializeV0AdvertisementResultKind np_ffi_SerializeV0AdvertisementResult_kind(SerializeV0AdvertisementResult result);

/// Casts a `SerializeV0AdvertisementResult` to the `Success` variant,
/// panicking in the case where the passed value is of a different enum variant.
ByteBuffer<24> np_ffi_SerializeV0AdvertisementResult_into_SUCCESS(SerializeV0AdvertisementResult result);

/// Attempts to create a builder for a new public section within
/// the advertisement builder behind this handle,
/// returning a handle to the newly-created section builder if successful.
///
/// This method may fail if there is another currently-active
/// section builder for the same advertisement builder, if the
/// kind of section being added does not match the advertisement
/// type (public/encrypted), or if the section would not manage
/// to fit within the enclosing advertisement.
CreateV1SectionBuilderResult np_ffi_V1AdvertisementBuilder_public_section_builder(V1AdvertisementBuilder adv_builder);

/// Attempts to create a builder for a new encrypted section within
/// the advertisement builder behind the given handle,
/// returning a handle to the newly-created section builder if successful.
///
/// The identity details for the new section builder may be specified
/// via providing the broadcast credential data, the kind of encrypted
/// identity being broadcast (private/trusted/provisioned), and the
/// verification mode (MIC/Signature) to be used for the encrypted section.
///
/// This method may fail if there is another currently-active
/// section builder for the same advertisement builder, if the
/// kind of section being added does not match the advertisement
/// type (public/encrypted), or if the section would not manage
/// to fit within the enclosing advertisement.
CreateV1SectionBuilderResult np_ffi_V1AdvertisementBuilder_encrypted_section_builder(V1AdvertisementBuilder adv_builder,
                                                                                     V1BroadcastCredential broadcast_cred,
                                                                                     V1VerificationMode verification_mode);

/// Attempts to serialize the contents of the advertisement builder
/// behind this handle to bytes. Assuming that the handle is valid,
/// this operation will always result in the contents behind the
/// advertisement builder handle being deallocated.
SerializeV1AdvertisementResult np_ffi_V1AdvertisementBuilder_into_advertisement(V1AdvertisementBuilder adv_builder);

/// Creates a new V1 advertisement builder for the given advertisement
/// kind (public/encrypted).
V1AdvertisementBuilder np_ffi_create_v1_advertisement_builder();

/// Gets the tag of a `SerializeV1AdvertisementResult` tagged-union.
SerializeV1AdvertisementResultKind np_ffi_SerializeV1AdvertisementResult_kind(SerializeV1AdvertisementResult result);

/// Casts a `SerializeV1AdvertisementResult` to the `Success` variant,
/// panicking in the case where the passed value is of a different enum variant.
ByteBuffer<250> np_ffi_SerializeV1AdvertisementResult_into_SUCCESS(SerializeV1AdvertisementResult result);

/// Gets the tag of a `CreateV1SectionBuilderResult` tagged-union.
CreateV1SectionBuilderResultKind np_ffi_CreateV1SectionBuilderResult_kind(CreateV1SectionBuilderResult result);

/// Casts a `CreateV1SectionBuilderResult` to the `Success` variant,
/// panicking in the case where the passed value is of a different enum variant.
V1SectionBuilder np_ffi_CreateV1SectionBuilderResult_into_SUCCESS(CreateV1SectionBuilderResult result);

/// Gets the tag of a `V1DE16ByteSaltResult` tagged-union.
V1DE16ByteSaltResultKind np_ffi_V1DE16ByteSaltResult_kind(V1DE16ByteSaltResult result);

/// Casts a `V1DE16ByteSaltResult` to the `Success` variant,
/// panicking in the case where the passed value is of a different enum variant.
FixedSizeArray<16> np_ffi_V1DE16ByteSaltResult_into_SUCCESS(V1DE16ByteSaltResult result);

/// Adds the section constructed behind the given handle to
/// a section builder to the containing advertisement it originated from.
/// After this call, the section builder handle will become invalid.
AddV1SectionToAdvertisementResult np_ffi_V1SectionBuilder_add_to_advertisement(V1SectionBuilder section_builder);

/// Attempts to get the derived 16-byte V1 DE salt for a
/// data element with the given type code in the context
/// of the passed section builder. May fail if this
/// section builder handle is invalid, if the section
/// is a public section, or if the DE type-code is
/// forbidden (0xFFFFFFFF).
V1DE16ByteSaltResult np_ffi_V1SectionBuilder_de_salt(V1SectionBuilder section_builder,
                                                     V1DEType de_type);

/// Attempts to add the given DE to the section builder behind
/// this handle. The passed DE may have a payload of up to 127
/// bytes, the maximum for a V1 DE.
AddV1DEResult np_ffi_V1SectionBuilder_add_generic_de(V1SectionBuilder section_builder,
                                                     GenericV1DataElement de);

/// Gets the tag of a `V0DataElement` tagged-union.
V0DataElementKind np_ffi_V0DataElement_kind(V0DataElement de);

/// Casts a `V0DataElement` to the `TxPower` variant, panicking in the
/// case where the passed value is of a different enum variant.
TxPower np_ffi_V0DataElement_into_TX_POWER(V0DataElement de);

/// Upcasts a Tx power DE to a generic V0 data-element.
V0DataElement np_ffi_TxPower_into_V0DataElement(TxPower tx_power);

/// Casts a `V0DataElement` to the `Actions` variant, panicking in the
/// case where the passed value is of a different enum variant.
V0Actions np_ffi_V0DataElement_into_ACTIONS(V0DataElement de);

/// Upcasts a V0 actions DE to a generic V0 data-element.
V0DataElement np_ffi_V0Actions_into_V0DataElement(V0Actions actions);

/// Gets the tag of a `BuildTxPowerResult` tagged-union.
BuildTxPowerResultKind np_ffi_BuildTxPowerResult_kind(BuildTxPowerResult result);

/// Casts a `BuildTxPowerResult` to the `Success` variant, panicking in the
/// case where the passed value is of a different enum variant.
TxPower np_ffi_BuildTxPowerResult_into_SUCCESS(BuildTxPowerResult result);

/// Attempts to construct a new TxPower from
/// the given signed-byte value.
BuildTxPowerResult np_ffi_TxPower_build_from_signed_byte(int8_t tx_power);

/// Gets the value of the given TxPower as a signed byte.
int8_t np_ffi_TxPower_as_signed_byte(TxPower tx_power);

/// Gets the discriminant of the `SetV0ActionResult` tagged-union.
SetV0ActionResultKind np_ffi_SetV0ActionResult_kind(SetV0ActionResult result);

/// Attempts to cast a `SetV0ActionResult` tagged-union into the `Success` variant.
V0Actions np_ffi_SetV0ActionResult_into_SUCCESS(SetV0ActionResult result);

/// Attempts to cast a `SetV0ActionResult` tagged-union into the `Error` variant.
V0Actions np_ffi_SetV0ActionResult_into_ERROR(SetV0ActionResult result);

/// Constructs a new V0 actions DE with no declared boolean
/// actions and a zeroed context sync sequence number,
/// where the DE is intended for the given advertisement
/// kind (plaintext/encrypted).
V0Actions np_ffi_build_new_zeroed_V0Actions(AdvertisementBuilderKind kind);

/// Return whether a boolean action type is set in this data element
bool np_ffi_V0Actions_has_action(V0Actions actions, ActionType action_type);

/// Attempts to set the given action bit to the given boolean value.
/// This operation may fail if the requested action bit may not be
/// set for the kind of containing advertisement (public/encrypted)
/// that this action DE is intended to belong to. In this case,
/// the original action bits will be yielded back to the caller,
/// unaltered.
SetV0ActionResult np_ffi_V0Actions_set_action(V0Actions actions,
                                              ActionType action_type,
                                              bool value);

/// Returns the representation of the passed `V0Actions` as an unsigned
/// integer, where the bit-positions correspond to individual actions.
uint32_t np_ffi_V0Actions_as_u32(V0Actions actions);

/// Extracts the numerical value of the given V1 DE type code as
/// an unsigned 32-bit integer.
uint32_t np_ffi_V1DEType_to_uint32_t(V1DEType de_type);

}  // extern "C"

}  // namespace internal
}  // namespace np_ffi

// clang-format on
