// Copyright 2025 Simo Sorce
// See LICENSE.txt file for terms

//! This module is automatically generated by `bindgen` from the
//! `PKCS #11 Headers` and includes all constants and objects
//! defined in the `PKCS #11 API` version selected for the build

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

use crate::error::Result;

include!(concat!(env!("OUT_DIR"), "/pkcs11_bindings.rs"));

// types that need different mutability than bindgen provides
pub type CK_FUNCTION_LIST_PTR = *const CK_FUNCTION_LIST;
pub type CK_FUNCTION_LIST_3_0_PTR = *const CK_FUNCTION_LIST_3_0;
pub type CK_FUNCTION_LIST_3_2_PTR = *const CK_FUNCTION_LIST_3_2;
// this is wrongly converted on 32b architecture to too large value
// which can not be represented in CK_ULONG.
pub const CK_UNAVAILABLE_INFORMATION: CK_ULONG = CK_ULONG::MAX;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct CK_INTERFACE {
    pub pInterfaceName: *const CK_CHAR,
    pub pFunctionList: *const ::std::os::raw::c_void,
    pub flags: CK_FLAGS,
}
unsafe impl Sync for CK_INTERFACE {}
unsafe impl Send for CK_INTERFACE {}

pub mod vendor;

macro_rules! const_to_elem {
    ($name:ident) => {
        ($name, stringify!($name))
    };
}

/// Static map with error num -> error string pairs
static ERRORMAP: [(CK_ULONG, &str); 104] = [
    const_to_elem!(CKR_OK),
    const_to_elem!(CKR_CANCEL),
    const_to_elem!(CKR_HOST_MEMORY),
    const_to_elem!(CKR_SLOT_ID_INVALID),
    const_to_elem!(CKR_GENERAL_ERROR),
    const_to_elem!(CKR_FUNCTION_FAILED),
    const_to_elem!(CKR_ARGUMENTS_BAD),
    const_to_elem!(CKR_NO_EVENT),
    const_to_elem!(CKR_NEED_TO_CREATE_THREADS),
    const_to_elem!(CKR_CANT_LOCK),
    const_to_elem!(CKR_ATTRIBUTE_READ_ONLY),
    const_to_elem!(CKR_ATTRIBUTE_SENSITIVE),
    const_to_elem!(CKR_ATTRIBUTE_TYPE_INVALID),
    const_to_elem!(CKR_ATTRIBUTE_VALUE_INVALID),
    const_to_elem!(CKR_ACTION_PROHIBITED),
    const_to_elem!(CKR_DATA_INVALID),
    const_to_elem!(CKR_DATA_LEN_RANGE),
    const_to_elem!(CKR_DEVICE_ERROR),
    const_to_elem!(CKR_DEVICE_MEMORY),
    const_to_elem!(CKR_DEVICE_REMOVED),
    const_to_elem!(CKR_ENCRYPTED_DATA_INVALID),
    const_to_elem!(CKR_ENCRYPTED_DATA_LEN_RANGE),
    const_to_elem!(CKR_AEAD_DECRYPT_FAILED),
    const_to_elem!(CKR_FUNCTION_CANCELED),
    const_to_elem!(CKR_FUNCTION_NOT_PARALLEL),
    const_to_elem!(CKR_FUNCTION_NOT_SUPPORTED),
    const_to_elem!(CKR_KEY_HANDLE_INVALID),
    const_to_elem!(CKR_KEY_SIZE_RANGE),
    const_to_elem!(CKR_KEY_TYPE_INCONSISTENT),
    const_to_elem!(CKR_KEY_NOT_NEEDED),
    const_to_elem!(CKR_KEY_CHANGED),
    const_to_elem!(CKR_KEY_NEEDED),
    const_to_elem!(CKR_KEY_INDIGESTIBLE),
    const_to_elem!(CKR_KEY_FUNCTION_NOT_PERMITTED),
    const_to_elem!(CKR_KEY_NOT_WRAPPABLE),
    const_to_elem!(CKR_KEY_UNEXTRACTABLE),
    const_to_elem!(CKR_MECHANISM_INVALID),
    const_to_elem!(CKR_MECHANISM_PARAM_INVALID),
    const_to_elem!(CKR_OBJECT_HANDLE_INVALID),
    const_to_elem!(CKR_OPERATION_ACTIVE),
    const_to_elem!(CKR_OPERATION_NOT_INITIALIZED),
    const_to_elem!(CKR_PIN_INCORRECT),
    const_to_elem!(CKR_PIN_INVALID),
    const_to_elem!(CKR_PIN_LEN_RANGE),
    const_to_elem!(CKR_PIN_EXPIRED),
    const_to_elem!(CKR_PIN_LOCKED),
    const_to_elem!(CKR_SESSION_CLOSED),
    const_to_elem!(CKR_SESSION_COUNT),
    const_to_elem!(CKR_SESSION_HANDLE_INVALID),
    const_to_elem!(CKR_SESSION_PARALLEL_NOT_SUPPORTED),
    const_to_elem!(CKR_SESSION_READ_ONLY),
    const_to_elem!(CKR_SESSION_EXISTS),
    const_to_elem!(CKR_SESSION_READ_ONLY_EXISTS),
    const_to_elem!(CKR_SESSION_READ_WRITE_SO_EXISTS),
    const_to_elem!(CKR_SIGNATURE_INVALID),
    const_to_elem!(CKR_SIGNATURE_LEN_RANGE),
    const_to_elem!(CKR_TEMPLATE_INCOMPLETE),
    const_to_elem!(CKR_TEMPLATE_INCONSISTENT),
    const_to_elem!(CKR_TOKEN_NOT_PRESENT),
    const_to_elem!(CKR_TOKEN_NOT_RECOGNIZED),
    const_to_elem!(CKR_TOKEN_WRITE_PROTECTED),
    const_to_elem!(CKR_UNWRAPPING_KEY_HANDLE_INVALID),
    const_to_elem!(CKR_UNWRAPPING_KEY_SIZE_RANGE),
    const_to_elem!(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT),
    const_to_elem!(CKR_USER_ALREADY_LOGGED_IN),
    const_to_elem!(CKR_USER_NOT_LOGGED_IN),
    const_to_elem!(CKR_USER_PIN_NOT_INITIALIZED),
    const_to_elem!(CKR_USER_TYPE_INVALID),
    const_to_elem!(CKR_USER_ANOTHER_ALREADY_LOGGED_IN),
    const_to_elem!(CKR_USER_TOO_MANY_TYPES),
    const_to_elem!(CKR_WRAPPED_KEY_INVALID),
    const_to_elem!(CKR_WRAPPED_KEY_LEN_RANGE),
    const_to_elem!(CKR_WRAPPING_KEY_HANDLE_INVALID),
    const_to_elem!(CKR_WRAPPING_KEY_SIZE_RANGE),
    const_to_elem!(CKR_WRAPPING_KEY_TYPE_INCONSISTENT),
    const_to_elem!(CKR_RANDOM_SEED_NOT_SUPPORTED),
    const_to_elem!(CKR_RANDOM_NO_RNG),
    const_to_elem!(CKR_DOMAIN_PARAMS_INVALID),
    const_to_elem!(CKR_CURVE_NOT_SUPPORTED),
    const_to_elem!(CKR_BUFFER_TOO_SMALL),
    const_to_elem!(CKR_SAVED_STATE_INVALID),
    const_to_elem!(CKR_INFORMATION_SENSITIVE),
    const_to_elem!(CKR_STATE_UNSAVEABLE),
    const_to_elem!(CKR_CRYPTOKI_NOT_INITIALIZED),
    const_to_elem!(CKR_CRYPTOKI_ALREADY_INITIALIZED),
    const_to_elem!(CKR_MUTEX_BAD),
    const_to_elem!(CKR_MUTEX_NOT_LOCKED),
    const_to_elem!(CKR_NEW_PIN_MODE),
    const_to_elem!(CKR_NEXT_OTP),
    const_to_elem!(CKR_EXCEEDED_MAX_ITERATIONS),
    const_to_elem!(CKR_FIPS_SELF_TEST_FAILED),
    const_to_elem!(CKR_LIBRARY_LOAD_FAILED),
    const_to_elem!(CKR_PIN_TOO_WEAK),
    const_to_elem!(CKR_PUBLIC_KEY_INVALID),
    const_to_elem!(CKR_FUNCTION_REJECTED),
    const_to_elem!(CKR_TOKEN_RESOURCE_EXCEEDED),
    const_to_elem!(CKR_OPERATION_CANCEL_FAILED),
    const_to_elem!(CKR_KEY_EXHAUSTED),
    const_to_elem!(CKR_PENDING),
    const_to_elem!(CKR_SESSION_ASYNC_NOT_SUPPORTED),
    const_to_elem!(CKR_SEED_RANDOM_REQUIRED),
    const_to_elem!(CKR_OPERATION_NOT_VALIDATED),
    const_to_elem!(CKR_TOKEN_NOT_INITIALIZED),
    const_to_elem!(CKR_PARAMETER_SET_NOT_SUPPORTED),
];

/// Function to return an error string from a CK_RV error.
///
/// It never fails and returns "Unknown Error XX" where XX
/// is an unknown error number (in hexadecimal notation).
pub fn ckrv_to_string(ckrv: CK_ULONG) -> String {
    for e in ERRORMAP {
        if e.0 == ckrv {
            return format!("{}({})", e.1, e.0);
        }
    }
    return format!("Unknown Error {:x}", ckrv);
}

/// Static map with mech num -> mech name pairs
static MECHMAP: [(CK_ULONG, &str); 470] = [
    const_to_elem!(CKM_AES_KEY_GEN),
    const_to_elem!(CKM_RSA_PKCS_KEY_PAIR_GEN),
    const_to_elem!(CKM_RSA_PKCS),
    const_to_elem!(CKM_RSA_9796),
    const_to_elem!(CKM_RSA_X_509),
    const_to_elem!(CKM_MD2_RSA_PKCS),
    const_to_elem!(CKM_MD5_RSA_PKCS),
    const_to_elem!(CKM_SHA1_RSA_PKCS),
    const_to_elem!(CKM_RIPEMD128_RSA_PKCS),
    const_to_elem!(CKM_RIPEMD160_RSA_PKCS),
    const_to_elem!(CKM_RSA_PKCS_OAEP),
    const_to_elem!(CKM_RSA_X9_31_KEY_PAIR_GEN),
    const_to_elem!(CKM_RSA_X9_31),
    const_to_elem!(CKM_SHA1_RSA_X9_31),
    const_to_elem!(CKM_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA1_RSA_PKCS_PSS),
    const_to_elem!(CKM_ML_KEM_KEY_PAIR_GEN),
    const_to_elem!(CKM_DSA_KEY_PAIR_GEN),
    const_to_elem!(CKM_DSA),
    const_to_elem!(CKM_DSA_SHA1),
    const_to_elem!(CKM_DSA_SHA224),
    const_to_elem!(CKM_DSA_SHA256),
    const_to_elem!(CKM_DSA_SHA384),
    const_to_elem!(CKM_DSA_SHA512),
    const_to_elem!(CKM_ML_KEM),
    const_to_elem!(CKM_DSA_SHA3_224),
    const_to_elem!(CKM_DSA_SHA3_256),
    const_to_elem!(CKM_DSA_SHA3_384),
    const_to_elem!(CKM_DSA_SHA3_512),
    const_to_elem!(CKM_ML_DSA_KEY_PAIR_GEN),
    const_to_elem!(CKM_ML_DSA),
    const_to_elem!(CKM_HASH_ML_DSA),
    const_to_elem!(CKM_DH_PKCS_KEY_PAIR_GEN),
    const_to_elem!(CKM_DH_PKCS_DERIVE),
    const_to_elem!(CKM_HASH_ML_DSA_SHA224),
    const_to_elem!(CKM_HASH_ML_DSA_SHA256),
    const_to_elem!(CKM_HASH_ML_DSA_SHA384),
    const_to_elem!(CKM_HASH_ML_DSA_SHA512),
    const_to_elem!(CKM_HASH_ML_DSA_SHA3_224),
    const_to_elem!(CKM_HASH_ML_DSA_SHA3_256),
    const_to_elem!(CKM_HASH_ML_DSA_SHA3_384),
    const_to_elem!(CKM_HASH_ML_DSA_SHA3_512),
    const_to_elem!(CKM_HASH_ML_DSA_SHAKE128),
    const_to_elem!(CKM_HASH_ML_DSA_SHAKE256),
    const_to_elem!(CKM_SLH_DSA_KEY_PAIR_GEN),
    const_to_elem!(CKM_SLH_DSA),
    const_to_elem!(CKM_X9_42_DH_KEY_PAIR_GEN),
    const_to_elem!(CKM_X9_42_DH_DERIVE),
    const_to_elem!(CKM_X9_42_DH_HYBRID_DERIVE),
    const_to_elem!(CKM_X9_42_MQV_DERIVE),
    const_to_elem!(CKM_HASH_SLH_DSA),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA224),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA256),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA384),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA512),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA3_224),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA3_256),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA3_384),
    const_to_elem!(CKM_HASH_SLH_DSA_SHA3_512),
    const_to_elem!(CKM_HASH_SLH_DSA_SHAKE128),
    const_to_elem!(CKM_HASH_SLH_DSA_SHAKE256),
    const_to_elem!(CKM_SHA256_RSA_PKCS),
    const_to_elem!(CKM_SHA384_RSA_PKCS),
    const_to_elem!(CKM_SHA512_RSA_PKCS),
    const_to_elem!(CKM_SHA256_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA384_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA512_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA224_RSA_PKCS),
    const_to_elem!(CKM_SHA224_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA512_224),
    const_to_elem!(CKM_SHA512_224_HMAC),
    const_to_elem!(CKM_SHA512_224_HMAC_GENERAL),
    const_to_elem!(CKM_SHA512_224_KEY_DERIVATION),
    const_to_elem!(CKM_SHA512_256),
    const_to_elem!(CKM_SHA512_256_HMAC),
    const_to_elem!(CKM_SHA512_256_HMAC_GENERAL),
    const_to_elem!(CKM_SHA512_256_KEY_DERIVATION),
    const_to_elem!(CKM_SHA512_T),
    const_to_elem!(CKM_SHA512_T_HMAC),
    const_to_elem!(CKM_SHA512_T_HMAC_GENERAL),
    const_to_elem!(CKM_SHA512_T_KEY_DERIVATION),
    const_to_elem!(CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE),
    const_to_elem!(CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH),
    const_to_elem!(CKM_SHA3_256_RSA_PKCS),
    const_to_elem!(CKM_SHA3_384_RSA_PKCS),
    const_to_elem!(CKM_SHA3_512_RSA_PKCS),
    const_to_elem!(CKM_SHA3_256_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA3_384_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA3_512_RSA_PKCS_PSS),
    const_to_elem!(CKM_SHA3_224_RSA_PKCS),
    const_to_elem!(CKM_SHA3_224_RSA_PKCS_PSS),
    const_to_elem!(CKM_RC2_KEY_GEN),
    const_to_elem!(CKM_RC2_ECB),
    const_to_elem!(CKM_RC2_CBC),
    const_to_elem!(CKM_RC2_MAC),
    const_to_elem!(CKM_RC2_MAC_GENERAL),
    const_to_elem!(CKM_RC2_CBC_PAD),
    const_to_elem!(CKM_RC4_KEY_GEN),
    const_to_elem!(CKM_RC4),
    const_to_elem!(CKM_DES_KEY_GEN),
    const_to_elem!(CKM_DES_ECB),
    const_to_elem!(CKM_DES_CBC),
    const_to_elem!(CKM_DES_MAC),
    const_to_elem!(CKM_DES_MAC_GENERAL),
    const_to_elem!(CKM_DES_CBC_PAD),
    const_to_elem!(CKM_DES2_KEY_GEN),
    const_to_elem!(CKM_DES3_KEY_GEN),
    const_to_elem!(CKM_DES3_ECB),
    const_to_elem!(CKM_DES3_CBC),
    const_to_elem!(CKM_DES3_MAC),
    const_to_elem!(CKM_DES3_MAC_GENERAL),
    const_to_elem!(CKM_DES3_CBC_PAD),
    const_to_elem!(CKM_DES3_CMAC_GENERAL),
    const_to_elem!(CKM_DES3_CMAC),
    const_to_elem!(CKM_CDMF_KEY_GEN),
    const_to_elem!(CKM_CDMF_ECB),
    const_to_elem!(CKM_CDMF_CBC),
    const_to_elem!(CKM_CDMF_MAC),
    const_to_elem!(CKM_CDMF_MAC_GENERAL),
    const_to_elem!(CKM_CDMF_CBC_PAD),
    const_to_elem!(CKM_DES_OFB64),
    const_to_elem!(CKM_DES_OFB8),
    const_to_elem!(CKM_DES_CFB64),
    const_to_elem!(CKM_DES_CFB8),
    const_to_elem!(CKM_MD2),
    const_to_elem!(CKM_MD2_HMAC),
    const_to_elem!(CKM_MD2_HMAC_GENERAL),
    const_to_elem!(CKM_MD5),
    const_to_elem!(CKM_MD5_HMAC),
    const_to_elem!(CKM_MD5_HMAC_GENERAL),
    const_to_elem!(CKM_SHA_1),
    const_to_elem!(CKM_SHA_1_HMAC),
    const_to_elem!(CKM_SHA_1_HMAC_GENERAL),
    const_to_elem!(CKM_RIPEMD128),
    const_to_elem!(CKM_RIPEMD128_HMAC),
    const_to_elem!(CKM_RIPEMD128_HMAC_GENERAL),
    const_to_elem!(CKM_RIPEMD160),
    const_to_elem!(CKM_RIPEMD160_HMAC),
    const_to_elem!(CKM_RIPEMD160_HMAC_GENERAL),
    const_to_elem!(CKM_SHA256),
    const_to_elem!(CKM_SHA256_HMAC),
    const_to_elem!(CKM_SHA256_HMAC_GENERAL),
    const_to_elem!(CKM_SHA224),
    const_to_elem!(CKM_SHA224_HMAC),
    const_to_elem!(CKM_SHA224_HMAC_GENERAL),
    const_to_elem!(CKM_SHA384),
    const_to_elem!(CKM_SHA384_HMAC),
    const_to_elem!(CKM_SHA384_HMAC_GENERAL),
    const_to_elem!(CKM_SHA512),
    const_to_elem!(CKM_SHA512_HMAC),
    const_to_elem!(CKM_SHA512_HMAC_GENERAL),
    const_to_elem!(CKM_SECURID_KEY_GEN),
    const_to_elem!(CKM_SECURID),
    const_to_elem!(CKM_HOTP_KEY_GEN),
    const_to_elem!(CKM_HOTP),
    const_to_elem!(CKM_ACTI),
    const_to_elem!(CKM_ACTI_KEY_GEN),
    const_to_elem!(CKM_SHA3_256),
    const_to_elem!(CKM_SHA3_256_HMAC),
    const_to_elem!(CKM_SHA3_256_HMAC_GENERAL),
    const_to_elem!(CKM_SHA3_256_KEY_GEN),
    const_to_elem!(CKM_SHA3_224),
    const_to_elem!(CKM_SHA3_224_HMAC),
    const_to_elem!(CKM_SHA3_224_HMAC_GENERAL),
    const_to_elem!(CKM_SHA3_224_KEY_GEN),
    const_to_elem!(CKM_SHA3_384),
    const_to_elem!(CKM_SHA3_384_HMAC),
    const_to_elem!(CKM_SHA3_384_HMAC_GENERAL),
    const_to_elem!(CKM_SHA3_384_KEY_GEN),
    const_to_elem!(CKM_SHA3_512),
    const_to_elem!(CKM_SHA3_512_HMAC),
    const_to_elem!(CKM_SHA3_512_HMAC_GENERAL),
    const_to_elem!(CKM_SHA3_512_KEY_GEN),
    const_to_elem!(CKM_CAST_KEY_GEN),
    const_to_elem!(CKM_CAST_ECB),
    const_to_elem!(CKM_CAST_CBC),
    const_to_elem!(CKM_CAST_MAC),
    const_to_elem!(CKM_CAST_MAC_GENERAL),
    const_to_elem!(CKM_CAST_CBC_PAD),
    const_to_elem!(CKM_CAST3_KEY_GEN),
    const_to_elem!(CKM_CAST3_ECB),
    const_to_elem!(CKM_CAST3_CBC),
    const_to_elem!(CKM_CAST3_MAC),
    const_to_elem!(CKM_CAST3_MAC_GENERAL),
    const_to_elem!(CKM_CAST3_CBC_PAD),
    const_to_elem!(CKM_CAST128_KEY_GEN),
    const_to_elem!(CKM_CAST128_ECB),
    const_to_elem!(CKM_CAST128_MAC),
    const_to_elem!(CKM_CAST128_CBC),
    const_to_elem!(CKM_CAST128_MAC_GENERAL),
    const_to_elem!(CKM_CAST128_CBC_PAD),
    const_to_elem!(CKM_RC5_KEY_GEN),
    const_to_elem!(CKM_RC5_ECB),
    const_to_elem!(CKM_RC5_CBC),
    const_to_elem!(CKM_RC5_MAC),
    const_to_elem!(CKM_RC5_MAC_GENERAL),
    const_to_elem!(CKM_RC5_CBC_PAD),
    const_to_elem!(CKM_IDEA_KEY_GEN),
    const_to_elem!(CKM_IDEA_ECB),
    const_to_elem!(CKM_IDEA_CBC),
    const_to_elem!(CKM_IDEA_MAC),
    const_to_elem!(CKM_IDEA_MAC_GENERAL),
    const_to_elem!(CKM_IDEA_CBC_PAD),
    const_to_elem!(CKM_GENERIC_SECRET_KEY_GEN),
    const_to_elem!(CKM_CONCATENATE_BASE_AND_KEY),
    const_to_elem!(CKM_CONCATENATE_BASE_AND_DATA),
    const_to_elem!(CKM_CONCATENATE_DATA_AND_BASE),
    const_to_elem!(CKM_XOR_BASE_AND_DATA),
    const_to_elem!(CKM_EXTRACT_KEY_FROM_KEY),
    const_to_elem!(CKM_SSL3_PRE_MASTER_KEY_GEN),
    const_to_elem!(CKM_SSL3_MASTER_KEY_DERIVE),
    const_to_elem!(CKM_SSL3_KEY_AND_MAC_DERIVE),
    const_to_elem!(CKM_SSL3_MASTER_KEY_DERIVE_DH),
    const_to_elem!(CKM_TLS_PRE_MASTER_KEY_GEN),
    const_to_elem!(CKM_TLS_MASTER_KEY_DERIVE),
    const_to_elem!(CKM_TLS_KEY_AND_MAC_DERIVE),
    const_to_elem!(CKM_TLS_MASTER_KEY_DERIVE_DH),
    const_to_elem!(CKM_TLS_PRF),
    const_to_elem!(CKM_SSL3_MD5_MAC),
    const_to_elem!(CKM_SSL3_SHA1_MAC),
    const_to_elem!(CKM_MD5_KEY_DERIVATION),
    const_to_elem!(CKM_MD2_KEY_DERIVATION),
    const_to_elem!(CKM_SHA1_KEY_DERIVATION),
    const_to_elem!(CKM_SHA256_KEY_DERIVATION),
    const_to_elem!(CKM_SHA384_KEY_DERIVATION),
    const_to_elem!(CKM_SHA512_KEY_DERIVATION),
    const_to_elem!(CKM_SHA224_KEY_DERIVATION),
    const_to_elem!(CKM_SHA3_256_KEY_DERIVATION),
    const_to_elem!(CKM_SHA3_256_KEY_DERIVE),
    const_to_elem!(CKM_SHA3_224_KEY_DERIVATION),
    const_to_elem!(CKM_SHA3_224_KEY_DERIVE),
    const_to_elem!(CKM_SHA3_384_KEY_DERIVATION),
    const_to_elem!(CKM_SHA3_384_KEY_DERIVE),
    const_to_elem!(CKM_SHA3_512_KEY_DERIVATION),
    const_to_elem!(CKM_SHA3_512_KEY_DERIVE),
    const_to_elem!(CKM_SHAKE_128_KEY_DERIVATION),
    const_to_elem!(CKM_SHAKE_128_KEY_DERIVE),
    const_to_elem!(CKM_SHAKE_256_KEY_DERIVATION),
    const_to_elem!(CKM_SHAKE_256_KEY_DERIVE),
    const_to_elem!(CKM_PBE_MD2_DES_CBC),
    const_to_elem!(CKM_PBE_MD5_DES_CBC),
    const_to_elem!(CKM_PBE_MD5_CAST_CBC),
    const_to_elem!(CKM_PBE_MD5_CAST3_CBC),
    const_to_elem!(CKM_PBE_MD5_CAST128_CBC),
    const_to_elem!(CKM_PBE_SHA1_CAST128_CBC),
    const_to_elem!(CKM_PBE_SHA1_RC4_128),
    const_to_elem!(CKM_PBE_SHA1_RC4_40),
    const_to_elem!(CKM_PBE_SHA1_DES3_EDE_CBC),
    const_to_elem!(CKM_PBE_SHA1_DES2_EDE_CBC),
    const_to_elem!(CKM_PBE_SHA1_RC2_128_CBC),
    const_to_elem!(CKM_PBE_SHA1_RC2_40_CBC),
    const_to_elem!(CKM_PKCS5_PBKD2),
    const_to_elem!(CKM_PBA_SHA1_WITH_SHA1_HMAC),
    const_to_elem!(CKM_WTLS_PRE_MASTER_KEY_GEN),
    const_to_elem!(CKM_WTLS_MASTER_KEY_DERIVE),
    const_to_elem!(CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC),
    const_to_elem!(CKM_WTLS_PRF),
    const_to_elem!(CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE),
    const_to_elem!(CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE),
    const_to_elem!(CKM_TLS10_MAC_SERVER),
    const_to_elem!(CKM_TLS10_MAC_CLIENT),
    const_to_elem!(CKM_TLS12_MAC),
    const_to_elem!(CKM_TLS12_KDF),
    const_to_elem!(CKM_TLS12_MASTER_KEY_DERIVE),
    const_to_elem!(CKM_TLS12_KEY_AND_MAC_DERIVE),
    const_to_elem!(CKM_TLS12_MASTER_KEY_DERIVE_DH),
    const_to_elem!(CKM_TLS12_KEY_SAFE_DERIVE),
    const_to_elem!(CKM_TLS_MAC),
    const_to_elem!(CKM_TLS_KDF),
    const_to_elem!(CKM_KEY_WRAP_LYNKS),
    const_to_elem!(CKM_KEY_WRAP_SET_OAEP),
    const_to_elem!(CKM_CMS_SIG),
    const_to_elem!(CKM_KIP_DERIVE),
    const_to_elem!(CKM_KIP_WRAP),
    const_to_elem!(CKM_KIP_MAC),
    const_to_elem!(CKM_CAMELLIA_KEY_GEN),
    const_to_elem!(CKM_CAMELLIA_ECB),
    const_to_elem!(CKM_CAMELLIA_CBC),
    const_to_elem!(CKM_CAMELLIA_MAC),
    const_to_elem!(CKM_CAMELLIA_MAC_GENERAL),
    const_to_elem!(CKM_CAMELLIA_CBC_PAD),
    const_to_elem!(CKM_CAMELLIA_ECB_ENCRYPT_DATA),
    const_to_elem!(CKM_CAMELLIA_CBC_ENCRYPT_DATA),
    const_to_elem!(CKM_CAMELLIA_CTR),
    const_to_elem!(CKM_ARIA_KEY_GEN),
    const_to_elem!(CKM_ARIA_ECB),
    const_to_elem!(CKM_ARIA_CBC),
    const_to_elem!(CKM_ARIA_MAC),
    const_to_elem!(CKM_ARIA_MAC_GENERAL),
    const_to_elem!(CKM_ARIA_CBC_PAD),
    const_to_elem!(CKM_ARIA_ECB_ENCRYPT_DATA),
    const_to_elem!(CKM_ARIA_CBC_ENCRYPT_DATA),
    const_to_elem!(CKM_SEED_KEY_GEN),
    const_to_elem!(CKM_SEED_ECB),
    const_to_elem!(CKM_SEED_CBC),
    const_to_elem!(CKM_SEED_MAC),
    const_to_elem!(CKM_SEED_MAC_GENERAL),
    const_to_elem!(CKM_SEED_CBC_PAD),
    const_to_elem!(CKM_SEED_ECB_ENCRYPT_DATA),
    const_to_elem!(CKM_SEED_CBC_ENCRYPT_DATA),
    const_to_elem!(CKM_SKIPJACK_KEY_GEN),
    const_to_elem!(CKM_SKIPJACK_ECB64),
    const_to_elem!(CKM_SKIPJACK_CBC64),
    const_to_elem!(CKM_SKIPJACK_OFB64),
    const_to_elem!(CKM_SKIPJACK_CFB64),
    const_to_elem!(CKM_SKIPJACK_CFB32),
    const_to_elem!(CKM_SKIPJACK_CFB16),
    const_to_elem!(CKM_SKIPJACK_CFB8),
    const_to_elem!(CKM_SKIPJACK_WRAP),
    const_to_elem!(CKM_SKIPJACK_PRIVATE_WRAP),
    const_to_elem!(CKM_SKIPJACK_RELAYX),
    const_to_elem!(CKM_KEA_KEY_PAIR_GEN),
    const_to_elem!(CKM_KEA_KEY_DERIVE),
    const_to_elem!(CKM_KEA_DERIVE),
    const_to_elem!(CKM_FORTEZZA_TIMESTAMP),
    const_to_elem!(CKM_BATON_KEY_GEN),
    const_to_elem!(CKM_BATON_ECB128),
    const_to_elem!(CKM_BATON_ECB96),
    const_to_elem!(CKM_BATON_CBC128),
    const_to_elem!(CKM_BATON_COUNTER),
    const_to_elem!(CKM_BATON_SHUFFLE),
    const_to_elem!(CKM_BATON_WRAP),
    const_to_elem!(CKM_EC_KEY_PAIR_GEN),
    const_to_elem!(CKM_ECDSA),
    const_to_elem!(CKM_ECDSA_SHA1),
    const_to_elem!(CKM_ECDSA_SHA224),
    const_to_elem!(CKM_ECDSA_SHA256),
    const_to_elem!(CKM_ECDSA_SHA384),
    const_to_elem!(CKM_ECDSA_SHA512),
    const_to_elem!(CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS),
    const_to_elem!(CKM_ECDH1_DERIVE),
    const_to_elem!(CKM_ECDH1_COFACTOR_DERIVE),
    const_to_elem!(CKM_ECMQV_DERIVE),
    const_to_elem!(CKM_ECDH_AES_KEY_WRAP),
    const_to_elem!(CKM_RSA_AES_KEY_WRAP),
    const_to_elem!(CKM_JUNIPER_KEY_GEN),
    const_to_elem!(CKM_JUNIPER_ECB128),
    const_to_elem!(CKM_JUNIPER_CBC128),
    const_to_elem!(CKM_JUNIPER_COUNTER),
    const_to_elem!(CKM_JUNIPER_SHUFFLE),
    const_to_elem!(CKM_JUNIPER_WRAP),
    const_to_elem!(CKM_FASTHASH),
    const_to_elem!(CKM_AES_XTS),
    const_to_elem!(CKM_AES_XTS_KEY_GEN),
    const_to_elem!(CKM_AES_KEY_GEN),
    const_to_elem!(CKM_AES_ECB),
    const_to_elem!(CKM_AES_CBC),
    const_to_elem!(CKM_AES_MAC),
    const_to_elem!(CKM_AES_MAC_GENERAL),
    const_to_elem!(CKM_AES_CBC_PAD),
    const_to_elem!(CKM_AES_CTR),
    const_to_elem!(CKM_AES_GCM),
    const_to_elem!(CKM_AES_CCM),
    const_to_elem!(CKM_AES_CTS),
    const_to_elem!(CKM_AES_CMAC),
    const_to_elem!(CKM_AES_CMAC_GENERAL),
    const_to_elem!(CKM_AES_XCBC_MAC),
    const_to_elem!(CKM_AES_XCBC_MAC_96),
    const_to_elem!(CKM_AES_GMAC),
    const_to_elem!(CKM_BLOWFISH_KEY_GEN),
    const_to_elem!(CKM_BLOWFISH_CBC),
    const_to_elem!(CKM_TWOFISH_KEY_GEN),
    const_to_elem!(CKM_TWOFISH_CBC),
    const_to_elem!(CKM_BLOWFISH_CBC_PAD),
    const_to_elem!(CKM_TWOFISH_CBC_PAD),
    const_to_elem!(CKM_DES_ECB_ENCRYPT_DATA),
    const_to_elem!(CKM_DES_CBC_ENCRYPT_DATA),
    const_to_elem!(CKM_DES3_ECB_ENCRYPT_DATA),
    const_to_elem!(CKM_DES3_CBC_ENCRYPT_DATA),
    const_to_elem!(CKM_AES_ECB_ENCRYPT_DATA),
    const_to_elem!(CKM_AES_CBC_ENCRYPT_DATA),
    const_to_elem!(CKM_GOSTR3410_KEY_PAIR_GEN),
    const_to_elem!(CKM_GOSTR3410),
    const_to_elem!(CKM_GOSTR3410_WITH_GOSTR3411),
    const_to_elem!(CKM_GOSTR3410_KEY_WRAP),
    const_to_elem!(CKM_GOSTR3410_DERIVE),
    const_to_elem!(CKM_GOSTR3411),
    const_to_elem!(CKM_GOSTR3411_HMAC),
    const_to_elem!(CKM_GOST28147_KEY_GEN),
    const_to_elem!(CKM_GOST28147_ECB),
    const_to_elem!(CKM_GOST28147),
    const_to_elem!(CKM_GOST28147_MAC),
    const_to_elem!(CKM_GOST28147_KEY_WRAP),
    const_to_elem!(CKM_CHACHA20_KEY_GEN),
    const_to_elem!(CKM_CHACHA20),
    const_to_elem!(CKM_POLY1305_KEY_GEN),
    const_to_elem!(CKM_POLY1305),
    const_to_elem!(CKM_DSA_PARAMETER_GEN),
    const_to_elem!(CKM_DH_PKCS_PARAMETER_GEN),
    const_to_elem!(CKM_X9_42_DH_PARAMETER_GEN),
    const_to_elem!(CKM_DSA_PROBABILISTIC_PARAMETER_GEN),
    const_to_elem!(CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN),
    const_to_elem!(CKM_DSA_FIPS_G_GEN),
    const_to_elem!(CKM_AES_OFB),
    const_to_elem!(CKM_AES_CFB64),
    const_to_elem!(CKM_AES_CFB8),
    const_to_elem!(CKM_AES_CFB128),
    const_to_elem!(CKM_AES_CFB1),
    const_to_elem!(CKM_AES_KEY_WRAP),
    const_to_elem!(CKM_AES_KEY_WRAP_PAD),
    const_to_elem!(CKM_AES_KEY_WRAP_KWP),
    const_to_elem!(CKM_AES_KEY_WRAP_PKCS7),
    const_to_elem!(CKM_RSA_PKCS_TPM_1_1),
    const_to_elem!(CKM_RSA_PKCS_OAEP_TPM_1_1),
    const_to_elem!(CKM_SHA_1_KEY_GEN),
    const_to_elem!(CKM_SHA224_KEY_GEN),
    const_to_elem!(CKM_SHA256_KEY_GEN),
    const_to_elem!(CKM_SHA384_KEY_GEN),
    const_to_elem!(CKM_SHA512_KEY_GEN),
    const_to_elem!(CKM_SHA512_224_KEY_GEN),
    const_to_elem!(CKM_SHA512_256_KEY_GEN),
    const_to_elem!(CKM_SHA512_T_KEY_GEN),
    const_to_elem!(CKM_NULL),
    const_to_elem!(CKM_BLAKE2B_160),
    const_to_elem!(CKM_BLAKE2B_160_HMAC),
    const_to_elem!(CKM_BLAKE2B_160_HMAC_GENERAL),
    const_to_elem!(CKM_BLAKE2B_160_KEY_DERIVE),
    const_to_elem!(CKM_BLAKE2B_160_KEY_GEN),
    const_to_elem!(CKM_BLAKE2B_256),
    const_to_elem!(CKM_BLAKE2B_256_HMAC),
    const_to_elem!(CKM_BLAKE2B_256_HMAC_GENERAL),
    const_to_elem!(CKM_BLAKE2B_256_KEY_DERIVE),
    const_to_elem!(CKM_BLAKE2B_256_KEY_GEN),
    const_to_elem!(CKM_BLAKE2B_384),
    const_to_elem!(CKM_BLAKE2B_384_HMAC),
    const_to_elem!(CKM_BLAKE2B_384_HMAC_GENERAL),
    const_to_elem!(CKM_BLAKE2B_384_KEY_DERIVE),
    const_to_elem!(CKM_BLAKE2B_384_KEY_GEN),
    const_to_elem!(CKM_BLAKE2B_512),
    const_to_elem!(CKM_BLAKE2B_512_HMAC),
    const_to_elem!(CKM_BLAKE2B_512_HMAC_GENERAL),
    const_to_elem!(CKM_BLAKE2B_512_KEY_DERIVE),
    const_to_elem!(CKM_BLAKE2B_512_KEY_GEN),
    const_to_elem!(CKM_SALSA20),
    const_to_elem!(CKM_CHACHA20_POLY1305),
    const_to_elem!(CKM_SALSA20_POLY1305),
    const_to_elem!(CKM_X3DH_INITIALIZE),
    const_to_elem!(CKM_X3DH_RESPOND),
    const_to_elem!(CKM_X2RATCHET_INITIALIZE),
    const_to_elem!(CKM_X2RATCHET_RESPOND),
    const_to_elem!(CKM_X2RATCHET_ENCRYPT),
    const_to_elem!(CKM_X2RATCHET_DECRYPT),
    const_to_elem!(CKM_XEDDSA),
    const_to_elem!(CKM_HKDF_DERIVE),
    const_to_elem!(CKM_HKDF_DATA),
    const_to_elem!(CKM_HKDF_KEY_GEN),
    const_to_elem!(CKM_SALSA20_KEY_GEN),
    const_to_elem!(CKM_ECDSA_SHA3_224),
    const_to_elem!(CKM_ECDSA_SHA3_256),
    const_to_elem!(CKM_ECDSA_SHA3_384),
    const_to_elem!(CKM_ECDSA_SHA3_512),
    const_to_elem!(CKM_EC_EDWARDS_KEY_PAIR_GEN),
    const_to_elem!(CKM_EC_MONTGOMERY_KEY_PAIR_GEN),
    const_to_elem!(CKM_EDDSA),
    const_to_elem!(CKM_SP800_108_COUNTER_KDF),
    const_to_elem!(CKM_SP800_108_FEEDBACK_KDF),
    const_to_elem!(CKM_SP800_108_DOUBLE_PIPELINE_KDF),
    const_to_elem!(CKM_IKE2_PRF_PLUS_DERIVE),
    const_to_elem!(CKM_IKE_PRF_DERIVE),
    const_to_elem!(CKM_IKE1_PRF_DERIVE),
    const_to_elem!(CKM_IKE1_EXTENDED_DERIVE),
    const_to_elem!(CKM_HSS_KEY_PAIR_GEN),
    const_to_elem!(CKM_HSS),
    const_to_elem!(CKM_XMSS_KEY_PAIR_GEN),
    const_to_elem!(CKM_XMSSMT_KEY_PAIR_GEN),
    const_to_elem!(CKM_XMSS),
    const_to_elem!(CKM_XMSSMT),
    const_to_elem!(CKM_ECDH_X_AES_KEY_WRAP),
    const_to_elem!(CKM_ECDH_COF_AES_KEY_WRAP),
    const_to_elem!(CKM_PUB_KEY_FROM_PRIV_KEY),
];

/// Static map with attribute num -> attribute name pairs
static ATTRMAP: &[(CK_ULONG, &str)] = &[
    const_to_elem!(CKA_CLASS),
    const_to_elem!(CKA_TOKEN),
    const_to_elem!(CKA_PRIVATE),
    const_to_elem!(CKA_LABEL),
    const_to_elem!(CKA_UNIQUE_ID),
    const_to_elem!(CKA_APPLICATION),
    const_to_elem!(CKA_VALUE),
    const_to_elem!(CKA_OBJECT_ID),
    const_to_elem!(CKA_CERTIFICATE_TYPE),
    const_to_elem!(CKA_ISSUER),
    const_to_elem!(CKA_SERIAL_NUMBER),
    const_to_elem!(CKA_AC_ISSUER),
    const_to_elem!(CKA_OWNER),
    const_to_elem!(CKA_ATTR_TYPES),
    const_to_elem!(CKA_TRUSTED),
    const_to_elem!(CKA_CERTIFICATE_CATEGORY),
    const_to_elem!(CKA_JAVA_MIDP_SECURITY_DOMAIN),
    const_to_elem!(CKA_URL),
    const_to_elem!(CKA_HASH_OF_SUBJECT_PUBLIC_KEY),
    const_to_elem!(CKA_HASH_OF_ISSUER_PUBLIC_KEY),
    const_to_elem!(CKA_NAME_HASH_ALGORITHM),
    const_to_elem!(CKA_CHECK_VALUE),
    const_to_elem!(CKA_KEY_TYPE),
    const_to_elem!(CKA_SUBJECT),
    const_to_elem!(CKA_ID),
    const_to_elem!(CKA_SENSITIVE),
    const_to_elem!(CKA_ENCRYPT),
    const_to_elem!(CKA_DECRYPT),
    const_to_elem!(CKA_WRAP),
    const_to_elem!(CKA_UNWRAP),
    const_to_elem!(CKA_SIGN),
    const_to_elem!(CKA_SIGN_RECOVER),
    const_to_elem!(CKA_VERIFY),
    const_to_elem!(CKA_VERIFY_RECOVER),
    const_to_elem!(CKA_DERIVE),
    const_to_elem!(CKA_START_DATE),
    const_to_elem!(CKA_END_DATE),
    const_to_elem!(CKA_MODULUS),
    const_to_elem!(CKA_MODULUS_BITS),
    const_to_elem!(CKA_PUBLIC_EXPONENT),
    const_to_elem!(CKA_PRIVATE_EXPONENT),
    const_to_elem!(CKA_PRIME_1),
    const_to_elem!(CKA_PRIME_2),
    const_to_elem!(CKA_EXPONENT_1),
    const_to_elem!(CKA_EXPONENT_2),
    const_to_elem!(CKA_COEFFICIENT),
    const_to_elem!(CKA_PUBLIC_KEY_INFO),
    const_to_elem!(CKA_PRIME),
    const_to_elem!(CKA_SUBPRIME),
    const_to_elem!(CKA_BASE),
    const_to_elem!(CKA_PRIME_BITS),
    const_to_elem!(CKA_SUBPRIME_BITS),
    const_to_elem!(CKA_SUB_PRIME_BITS),
    const_to_elem!(CKA_VALUE_BITS),
    const_to_elem!(CKA_VALUE_LEN),
    const_to_elem!(CKA_EXTRACTABLE),
    const_to_elem!(CKA_LOCAL),
    const_to_elem!(CKA_NEVER_EXTRACTABLE),
    const_to_elem!(CKA_ALWAYS_SENSITIVE),
    const_to_elem!(CKA_KEY_GEN_MECHANISM),
    const_to_elem!(CKA_MODIFIABLE),
    const_to_elem!(CKA_COPYABLE),
    const_to_elem!(CKA_DESTROYABLE),
    const_to_elem!(CKA_EC_PARAMS),
    const_to_elem!(CKA_EC_POINT),
    const_to_elem!(CKA_ALWAYS_AUTHENTICATE),
    const_to_elem!(CKA_WRAP_WITH_TRUSTED),
    const_to_elem!(CKA_OTP_FORMAT),
    const_to_elem!(CKA_OTP_LENGTH),
    const_to_elem!(CKA_OTP_TIME_INTERVAL),
    const_to_elem!(CKA_OTP_USER_FRIENDLY_MODE),
    const_to_elem!(CKA_OTP_CHALLENGE_REQUIREMENT),
    const_to_elem!(CKA_OTP_TIME_REQUIREMENT),
    const_to_elem!(CKA_OTP_COUNTER_REQUIREMENT),
    const_to_elem!(CKA_OTP_PIN_REQUIREMENT),
    const_to_elem!(CKA_OTP_COUNTER),
    const_to_elem!(CKA_OTP_TIME),
    const_to_elem!(CKA_OTP_USER_IDENTIFIER),
    const_to_elem!(CKA_OTP_SERVICE_IDENTIFIER),
    const_to_elem!(CKA_OTP_SERVICE_LOGO),
    const_to_elem!(CKA_OTP_SERVICE_LOGO_TYPE),
    const_to_elem!(CKA_GOSTR3410_PARAMS),
    const_to_elem!(CKA_GOSTR3411_PARAMS),
    const_to_elem!(CKA_GOST28147_PARAMS),
    const_to_elem!(CKA_HW_FEATURE_TYPE),
    const_to_elem!(CKA_RESET_ON_INIT),
    const_to_elem!(CKA_HAS_RESET),
    const_to_elem!(CKA_PIXEL_X),
    const_to_elem!(CKA_PIXEL_Y),
    const_to_elem!(CKA_RESOLUTION),
    const_to_elem!(CKA_CHAR_ROWS),
    const_to_elem!(CKA_CHAR_COLUMNS),
    const_to_elem!(CKA_COLOR),
    const_to_elem!(CKA_BITS_PER_PIXEL),
    const_to_elem!(CKA_CHAR_SETS),
    const_to_elem!(CKA_ENCODING_METHODS),
    const_to_elem!(CKA_MIME_TYPES),
    const_to_elem!(CKA_MECHANISM_TYPE),
    const_to_elem!(CKA_REQUIRED_CMS_ATTRIBUTES),
    const_to_elem!(CKA_DEFAULT_CMS_ATTRIBUTES),
    const_to_elem!(CKA_SUPPORTED_CMS_ATTRIBUTES),
    const_to_elem!(CKA_PROFILE_ID),
    const_to_elem!(CKA_X2RATCHET_BAG),
    const_to_elem!(CKA_X2RATCHET_BAGSIZE),
    const_to_elem!(CKA_X2RATCHET_BOBS1STMSG),
    const_to_elem!(CKA_X2RATCHET_CKR),
    const_to_elem!(CKA_X2RATCHET_CKS),
    const_to_elem!(CKA_X2RATCHET_DHP),
    const_to_elem!(CKA_X2RATCHET_DHR),
    const_to_elem!(CKA_X2RATCHET_DHS),
    const_to_elem!(CKA_X2RATCHET_HKR),
    const_to_elem!(CKA_X2RATCHET_HKS),
    const_to_elem!(CKA_X2RATCHET_ISALICE),
    const_to_elem!(CKA_X2RATCHET_NHKR),
    const_to_elem!(CKA_X2RATCHET_NHKS),
    const_to_elem!(CKA_X2RATCHET_NR),
    const_to_elem!(CKA_X2RATCHET_NS),
    const_to_elem!(CKA_X2RATCHET_PNS),
    const_to_elem!(CKA_X2RATCHET_RK),
    const_to_elem!(CKA_HSS_LEVELS),
    const_to_elem!(CKA_HSS_LMS_TYPE),
    const_to_elem!(CKA_HSS_LMOTS_TYPE),
    const_to_elem!(CKA_HSS_LMS_TYPES),
    const_to_elem!(CKA_HSS_LMOTS_TYPES),
    const_to_elem!(CKA_HSS_KEYS_REMAINING),
    const_to_elem!(CKA_PARAMETER_SET),
    const_to_elem!(CKA_OBJECT_VALIDATION_FLAGS),
    const_to_elem!(CKA_VALIDATION_TYPE),
    const_to_elem!(CKA_VALIDATION_VERSION),
    const_to_elem!(CKA_VALIDATION_LEVEL),
    const_to_elem!(CKA_VALIDATION_MODULE_ID),
    const_to_elem!(CKA_VALIDATION_FLAG),
    const_to_elem!(CKA_VALIDATION_AUTHORITY_TYPE),
    const_to_elem!(CKA_VALIDATION_COUNTRY),
    const_to_elem!(CKA_VALIDATION_CERTIFICATE_IDENTIFIER),
    const_to_elem!(CKA_VALIDATION_CERTIFICATE_URI),
    const_to_elem!(CKA_VALIDATION_VENDOR_URI),
    const_to_elem!(CKA_VALIDATION_PROFILE),
    const_to_elem!(CKA_ENCAPSULATE_TEMPLATE),
    const_to_elem!(CKA_DECAPSULATE_TEMPLATE),
    const_to_elem!(CKA_TRUST_SERVER_AUTH),
    const_to_elem!(CKA_TRUST_CLIENT_AUTH),
    const_to_elem!(CKA_TRUST_CODE_SIGNING),
    const_to_elem!(CKA_TRUST_EMAIL_PROTECTION),
    const_to_elem!(CKA_TRUST_IPSEC_IKE),
    const_to_elem!(CKA_TRUST_TIME_STAMPING),
    const_to_elem!(CKA_TRUST_OCSP_SIGNING),
    const_to_elem!(CKA_ENCAPSULATE),
    const_to_elem!(CKA_DECAPSULATE),
    const_to_elem!(CKA_HASH_OF_CERTIFICATE),
    const_to_elem!(CKA_PUBLIC_CRC64_VALUE),
    const_to_elem!(CKA_SEED),
    const_to_elem!(CKA_WRAP_TEMPLATE),
    const_to_elem!(CKA_UNWRAP_TEMPLATE),
    const_to_elem!(CKA_DERIVE_TEMPLATE),
    const_to_elem!(CKA_ALLOWED_MECHANISMS),
    const_to_elem!(CKA_VENDOR_DEFINED),
];

/// Static map with object class num -> object class name pairs
static OBJMAP: &[(CK_ULONG, &str)] = &[
    const_to_elem!(CKO_DATA),
    const_to_elem!(CKO_CERTIFICATE),
    const_to_elem!(CKO_PUBLIC_KEY),
    const_to_elem!(CKO_PRIVATE_KEY),
    const_to_elem!(CKO_SECRET_KEY),
    const_to_elem!(CKO_HW_FEATURE),
    const_to_elem!(CKO_DOMAIN_PARAMETERS),
    const_to_elem!(CKO_MECHANISM),
    const_to_elem!(CKO_OTP_KEY),
    const_to_elem!(CKO_PROFILE),
    const_to_elem!(CKO_VALIDATION),
    const_to_elem!(CKO_TRUST),
    const_to_elem!(CKO_VENDOR_DEFINED),
];

pub fn name_to_mech(name: &str) -> Result<CK_MECHANISM_TYPE> {
    for e in MECHMAP {
        if e.1 == name {
            return Ok(e.0);
        }
    }
    Err(CKR_ARGUMENTS_BAD)?
}

pub fn name_to_attr(name: &str) -> Result<CK_ATTRIBUTE_TYPE> {
    for e in ATTRMAP {
        if e.1 == name {
            return Ok(e.0);
        }
    }
    Err(CKR_ARGUMENTS_BAD)?
}

pub fn name_to_obj(name: &str) -> Result<CK_OBJECT_CLASS> {
    for e in OBJMAP {
        if e.1 == name {
            return Ok(e.0);
        }
    }
    Err(CKR_ARGUMENTS_BAD)?
}

/// Convenience helper to copy a pointer+length obtained via FFI into a
/// valid Vector of bytes.
macro_rules! bytes_to_vec {
    ($ptr:expr, $len:expr) => {{
        let ptr = $ptr as *const u8;
        let size = usize::try_from($len).unwrap();
        if ptr == std::ptr::null_mut() || size == 0 {
            Vec::new()
        } else {
            let mut v = Vec::<u8>::with_capacity(size);
            unsafe {
                std::ptr::copy_nonoverlapping(ptr, v.as_mut_ptr(), size);
                v.set_len(size);
            }
            v
        }
    }};
}

/// Date digits separator
const ASCII_DASH: u8 = b'-';
/// Smallest ASCII value for a date digit
const MIN_ASCII_DIGIT: u8 = b'0';
/// Largest ASCII value for a date digit
const MAX_ASCII_DIGIT: u8 = b'9';

/// Converts a vector of bytes into a CK_DATE structure with some validation
///
/// The data is checked to ensure only ASCII values of numbers are present,
/// but there is no validation that the resulting date is in any way valid.
pub fn vec_to_date_validate(val: Vec<u8>) -> Result<CK_DATE> {
    if val.len() != 8 {
        return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
    }
    for n in val.iter() {
        if *n < MIN_ASCII_DIGIT || *n > MAX_ASCII_DIGIT {
            return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
        }
    }
    Ok(CK_DATE {
        year: [val[0], val[1], val[2], val[3]],
        month: [val[4], val[5]],
        day: [val[6], val[7]],
    })
}

/// Parses a string as a date
///
/// Returns a CK_DATE on success
pub fn string_to_ck_date(date: &str) -> Result<CK_DATE> {
    let s = date.as_bytes().to_vec();
    if s.len() != 10 {
        return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
    }
    if s[4] != ASCII_DASH || s[7] != ASCII_DASH {
        return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
    }
    let mut buf = vec![0; 8];
    buf[0] = s[0];
    buf[1] = s[1];
    buf[2] = s[2];
    buf[3] = s[3];
    buf[4] = s[5];
    buf[5] = s[6];
    buf[6] = s[8];
    buf[7] = s[9];
    vec_to_date_validate(buf)
}

impl CK_ATTRIBUTE {
    /// Returns the internal data memory buffer as a CK_ULONG
    ///
    /// Errors out if the data size does not match the size of a CK_ULONG
    pub fn to_ulong(&self) -> Result<CK_ULONG> {
        if self.ulValueLen != std::mem::size_of::<CK_ULONG>() as CK_ULONG {
            return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
        }
        Ok(unsafe { *(self.pValue as CK_ULONG_PTR) })
    }

    /// Returns the internal data memory buffer as a bool
    ///
    /// Errors out if the data size does not match the size of a CK_BBOOL
    pub fn to_bool(self) -> Result<bool> {
        if self.ulValueLen != std::mem::size_of::<CK_BBOOL>() as CK_ULONG {
            return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
        }
        let val: CK_BBOOL = unsafe { *(self.pValue as CK_BBOOL_PTR) };
        if val == 0 {
            Ok(false)
        } else {
            Ok(true)
        }
    }

    /// Returns the internal data memory buffer as a String
    ///
    /// Errors out if the data size does not match or the buffer is
    /// not parseable as a UTF8 string.
    pub fn to_string(&self) -> Result<String> {
        if self.ulValueLen == 0 {
            return Ok(String::new());
        }
        if self.pValue.is_null() {
            return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
        }
        let buf: &[u8] = unsafe {
            std::slice::from_raw_parts(
                self.pValue as *const _,
                usize::try_from(self.ulValueLen)?,
            )
        };
        match std::str::from_utf8(buf) {
            Ok(s) => Ok(s.to_string()),
            Err(_) => Err(CKR_ATTRIBUTE_VALUE_INVALID)?,
        }
    }

    /// Returns the internal data memory buffer as a slice
    ///
    /// Errors out if the internal data pointer is null
    pub fn to_slice(&self) -> Result<&[u8]> {
        if self.ulValueLen == 0 {
            return Ok(&[]);
        }
        if self.pValue.is_null() {
            return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
        }
        Ok(unsafe {
            std::slice::from_raw_parts(
                self.pValue as *const u8,
                usize::try_from(self.ulValueLen)?,
            )
        })
    }

    /// Returns a copy of the internal buffer as an vector
    ///
    /// Returns an empty vector if the internal buffer pointer is null
    pub fn to_buf(&self) -> Result<Vec<u8>> {
        Ok(bytes_to_vec!(self.pValue, self.ulValueLen))
    }

    /// Returns the internal buffer as a CK_DATE
    ///
    /// Errors out if parsing the buffer as a date fails
    pub fn to_date(&self) -> Result<CK_DATE> {
        if self.ulValueLen == 0 {
            /* set 0000-00-00 */
            return Ok(CK_DATE {
                year: [b'0', b'0', b'0', b'0'],
                month: [b'0', b'0'],
                day: [b'0', b'0'],
            });
        }
        if self.pValue.is_null() {
            return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
        }
        if self.ulValueLen != 8 {
            return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
        }
        vec_to_date_validate(bytes_to_vec!(self.pValue, self.ulValueLen))
    }
}
