/*
 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.
*/


#pragma once

/* Generated with cbindgen:0.24.5 */

/*
 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));

/// 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);

/// Sets the maximum number of active handles to credential slabs
/// which may be active at any one time.
/// Default value: Max value.
/// Max value: `u32::MAX - 1`.
///
/// Useful for bounding the maximum memory used by the client application
/// on credential slabs in constrained-memory environments.
///
/// 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 API
/// call utilizing credential slabs.
void np_ffi_global_config_set_max_num_credential_slabs(uint32_t max_num_credential_slabs);

/// Sets the maximum number of active handles to credential books
/// which may be active at any one time.
/// Default value: Max value.
/// Max value: `u32::MAX - 1`.
///
/// Useful for bounding the maximum memory used by the client application
/// on credential books in constrained-memory environments.
///
/// 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 API
/// call utilizing credential books.
void np_ffi_global_config_set_max_num_credential_books(uint32_t max_num_credential_books);

/// Sets the maximum number of active handles to deserialized v0
/// advertisements which may be active at any one time.
///
/// Useful for bounding the maximum memory used by the client application
/// on v0 advertisements in constrained-memory environments.
///
/// Default value: Max value.
/// Max value: `u32::MAX - 1`.
///
/// 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 API
/// call which references or returns a deserialized V0 advertisement.
void np_ffi_global_config_set_max_num_deserialized_v0_advertisements(uint32_t max_num_deserialized_v0_advertisements);

/// Sets the maximum number of active handles to deserialized v1
/// advertisements which may be active at any one time.
///
/// Useful for bounding the maximum memory used by the client application
/// on v1 advertisements in constrained-memory environments.
///
/// Default value: Max value.
/// Max value: `u32::MAX - 1`.
///
/// 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 API
/// call which references or returns a deserialized V1 advertisement.
void np_ffi_global_config_set_max_num_deserialized_v1_advertisements(uint32_t max_num_deserialized_v1_advertisements);

/// 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
CreateCredentialSlabResult np_ffi_create_credential_slab();

/// Gets the tag of a `CreateCredentialSlabResult` tagged enum.
CreateCredentialSlabResultKind np_ffi_CreateCredentialSlabResult_kind(CreateCredentialSlabResult result);

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

/// 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.
AddCredentialToSlabResult 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.
AddCredentialToSlabResult np_ffi_CredentialSlab_add_v1_credential(CredentialSlab credential_slab,
                                                                  V1MatchableCredential v1_cred);

/// 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);

/// 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 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);

/// 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);

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

/// Gets the 4 bit context sync sequence number as a u8 from this data element
uint8_t np_ffi_V0Actions_get_context_sync_sequence_number(V0Actions actions);

/// Return whether a boolean action type is set in this data element
uint32_t np_ffi_V0Actions_as_u32(V0Actions actions);

/// 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 tag of the `GetV1DEResult` tagged-union.
GetV1DEResultKind np_ffi_GetV1DEResult_kind(GetV1DEResult result);

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

/// Converts a `V1DataElement` to a `GenericV1DataElement` which
/// only maintains information about the DE's type-code and payload.
GenericV1DataElement np_ffi_V1DataElement_to_generic(V1DataElement de);

/// 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
