/* cipher.c generated by valac 0.56.19, the Vala compiler
 * generated from cipher.vala, do not modify */

#include "crypto-vala.h"
#include <gcrypt.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include <gobject/gvaluecollector.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

#define _g_free0(var) (var = (g_free (var), NULL))
#define _crypto_symmetric_cipher_unref0(var) ((var == NULL) ? NULL : (var = (crypto_symmetric_cipher_unref (var), NULL)))
typedef struct _CryptoParamSpecSymmetricCipher CryptoParamSpecSymmetricCipher;

struct _CryptoSymmetricCipherPrivate {
	gcry_cipher_hd_t cipher;
};

struct _CryptoParamSpecSymmetricCipher {
	GParamSpec parent_instance;
};

static gint CryptoSymmetricCipher_private_offset;
static gpointer crypto_symmetric_cipher_parent_class = NULL;

static gboolean crypto_symmetric_cipher_parse (const gchar* algo_name,
                                        enum gcry_cipher_algos* algo,
                                        enum gcry_cipher_modes* mode,
                                        enum gcry_cipher_flags* flags);
static const gchar* crypto_symmetric_cipher_mode_to_string (enum gcry_cipher_modes mode);
static enum gcry_cipher_modes crypto_symmetric_cipher_mode_from_string (const gchar* name);
static gchar* crypto_symmetric_cipher_flags_to_string (enum gcry_cipher_flags flags);
static enum gcry_cipher_flags crypto_symmetric_cipher_flag_from_string (const gchar* flag_name);
static enum gcry_cipher_flags crypto_symmetric_cipher_flags_from_string (const gchar* flag_names);
static gchar* crypto_symmetric_cipher_to_algo_name (enum gcry_cipher_algos algo,
                                             enum gcry_cipher_modes mode,
                                             enum gcry_cipher_flags flags);
static CryptoSymmetricCipher* crypto_symmetric_cipher_new_gcrypt (enum gcry_cipher_algos algo,
                                                           enum gcry_cipher_modes mode,
                                                           enum gcry_cipher_flags flags,
                                                           GError** error);
static CryptoSymmetricCipher* crypto_symmetric_cipher_construct_gcrypt (GType object_type,
                                                                 enum gcry_cipher_algos algo,
                                                                 enum gcry_cipher_modes mode,
                                                                 enum gcry_cipher_flags flags,
                                                                 GError** error);
VALA_EXTERN void crypto_may_throw_gcrypt_error (gcry_error_t e,
                                    GError** error);
static void crypto_symmetric_cipher_finalize (CryptoSymmetricCipher * obj);
static GType crypto_symmetric_cipher_get_type_once (void);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);
static gssize _vala_array_length (gpointer array);

static inline gpointer
crypto_symmetric_cipher_get_instance_private (CryptoSymmetricCipher* self)
{
	return G_STRUCT_MEMBER_P (self, CryptoSymmetricCipher_private_offset);
}

gboolean
crypto_symmetric_cipher_supports (const gchar* algo_name)
{
	enum gcry_cipher_algos algo = 0;
	enum gcry_cipher_modes mode = 0;
	enum gcry_cipher_flags flags = 0;
	enum gcry_cipher_algos _tmp0_ = 0;
	enum gcry_cipher_modes _tmp1_ = 0;
	enum gcry_cipher_flags _tmp2_ = 0;
	gboolean _tmp3_;
	gboolean result;
	g_return_val_if_fail (algo_name != NULL, FALSE);
	_tmp3_ = crypto_symmetric_cipher_parse (algo_name, &_tmp0_, &_tmp1_, &_tmp2_);
	algo = _tmp0_;
	mode = _tmp1_;
	flags = _tmp2_;
	result = _tmp3_;
	return result;
}

static const gchar*
crypto_symmetric_cipher_mode_to_string (enum gcry_cipher_modes mode)
{
	const gchar* result;
	switch (mode) {
		case GCRY_CIPHER_MODE_ECB:
		{
			result = "ECB";
			return result;
		}
		case GCRY_CIPHER_MODE_CFB:
		{
			result = "CFB";
			return result;
		}
		case GCRY_CIPHER_MODE_CBC:
		{
			result = "CBC";
			return result;
		}
		case GCRY_CIPHER_MODE_STREAM:
		{
			result = "STREAM";
			return result;
		}
		case GCRY_CIPHER_MODE_OFB:
		{
			result = "OFB";
			return result;
		}
		case GCRY_CIPHER_MODE_CTR:
		{
			result = "CTR";
			return result;
		}
		case GCRY_CIPHER_MODE_AESWRAP:
		{
			result = "AESWRAP";
			return result;
		}
		case GCRY_CIPHER_MODE_GCM:
		{
			result = "GCM";
			return result;
		}
		case GCRY_CIPHER_MODE_POLY1305:
		{
			result = "POLY1305";
			return result;
		}
		case GCRY_CIPHER_MODE_OCB:
		{
			result = "OCB";
			return result;
		}
		case GCRY_CIPHER_MODE_CFB8:
		{
			result = "CFB8";
			return result;
		}
		default:
		break;
	}
	result = "NONE";
	return result;
}

static enum gcry_cipher_modes
crypto_symmetric_cipher_mode_from_string (const gchar* name)
{
	const gchar* _tmp0_;
	GQuark _tmp2_ = 0U;
	static GQuark _tmp1_label0 = 0;
	static GQuark _tmp1_label1 = 0;
	static GQuark _tmp1_label2 = 0;
	static GQuark _tmp1_label3 = 0;
	static GQuark _tmp1_label4 = 0;
	static GQuark _tmp1_label5 = 0;
	static GQuark _tmp1_label6 = 0;
	static GQuark _tmp1_label7 = 0;
	static GQuark _tmp1_label8 = 0;
	static GQuark _tmp1_label9 = 0;
	static GQuark _tmp1_label10 = 0;
	enum gcry_cipher_modes result;
	g_return_val_if_fail (name != NULL, 0);
	_tmp0_ = name;
	_tmp2_ = (NULL == _tmp0_) ? 0 : g_quark_from_string (_tmp0_);
	if (_tmp2_ == ((0 != _tmp1_label0) ? _tmp1_label0 : (_tmp1_label0 = g_quark_from_static_string ("ECB")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_ECB;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label1) ? _tmp1_label1 : (_tmp1_label1 = g_quark_from_static_string ("CFB")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_CFB;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label2) ? _tmp1_label2 : (_tmp1_label2 = g_quark_from_static_string ("CBC")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_CBC;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label3) ? _tmp1_label3 : (_tmp1_label3 = g_quark_from_static_string ("STREAM")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_STREAM;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label4) ? _tmp1_label4 : (_tmp1_label4 = g_quark_from_static_string ("OFB")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_OFB;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label5) ? _tmp1_label5 : (_tmp1_label5 = g_quark_from_static_string ("CTR")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_CTR;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label6) ? _tmp1_label6 : (_tmp1_label6 = g_quark_from_static_string ("AESWRAP")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_AESWRAP;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label7) ? _tmp1_label7 : (_tmp1_label7 = g_quark_from_static_string ("GCM")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_GCM;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label8) ? _tmp1_label8 : (_tmp1_label8 = g_quark_from_static_string ("POLY1305")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_POLY1305;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label9) ? _tmp1_label9 : (_tmp1_label9 = g_quark_from_static_string ("OCB")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_OCB;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label10) ? _tmp1_label10 : (_tmp1_label10 = g_quark_from_static_string ("CFB8")))) {
		switch (0) {
			default:
			{
				result = GCRY_CIPHER_MODE_CFB8;
				return result;
			}
		}
	}
	result = GCRY_CIPHER_MODE_NONE;
	return result;
}

static const gchar*
string_to_string (const gchar* self)
{
	const gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	result = self;
	return result;
}

static gchar*
crypto_symmetric_cipher_flags_to_string (enum gcry_cipher_flags flags)
{
	gchar* s = NULL;
	const gchar* _tmp28_ = NULL;
	const gchar* _tmp29_;
	gchar* _tmp30_;
	gchar* result;
	s = NULL;
	if ((GCRY_CIPHER_CBC_MAC & flags) != 0) {
		gchar* _tmp0_ = NULL;
		const gchar* _tmp1_;
		gchar* _tmp6_;
		_tmp1_ = s;
		if (_tmp1_ == NULL) {
			gchar* _tmp2_;
			_tmp2_ = g_strdup ("");
			_g_free0 (_tmp0_);
			_tmp0_ = _tmp2_;
		} else {
			const gchar* _tmp3_;
			const gchar* _tmp4_;
			gchar* _tmp5_;
			_tmp3_ = s;
			_tmp4_ = string_to_string (_tmp3_);
			_tmp5_ = g_strconcat (_tmp4_, "-", NULL);
			_g_free0 (_tmp0_);
			_tmp0_ = _tmp5_;
		}
		_tmp6_ = g_strconcat (_tmp0_, "MAC", NULL);
		_g_free0 (s);
		s = _tmp6_;
		_g_free0 (_tmp0_);
	}
	if ((GCRY_CIPHER_CBC_CTS & flags) != 0) {
		gchar* _tmp7_ = NULL;
		const gchar* _tmp8_;
		gchar* _tmp13_;
		_tmp8_ = s;
		if (_tmp8_ == NULL) {
			gchar* _tmp9_;
			_tmp9_ = g_strdup ("");
			_g_free0 (_tmp7_);
			_tmp7_ = _tmp9_;
		} else {
			const gchar* _tmp10_;
			const gchar* _tmp11_;
			gchar* _tmp12_;
			_tmp10_ = s;
			_tmp11_ = string_to_string (_tmp10_);
			_tmp12_ = g_strconcat (_tmp11_, "-", NULL);
			_g_free0 (_tmp7_);
			_tmp7_ = _tmp12_;
		}
		_tmp13_ = g_strconcat (_tmp7_, "CTS", NULL);
		_g_free0 (s);
		s = _tmp13_;
		_g_free0 (_tmp7_);
	}
	if ((GCRY_CIPHER_ENABLE_SYNC & flags) != 0) {
		gchar* _tmp14_ = NULL;
		const gchar* _tmp15_;
		gchar* _tmp20_;
		_tmp15_ = s;
		if (_tmp15_ == NULL) {
			gchar* _tmp16_;
			_tmp16_ = g_strdup ("");
			_g_free0 (_tmp14_);
			_tmp14_ = _tmp16_;
		} else {
			const gchar* _tmp17_;
			const gchar* _tmp18_;
			gchar* _tmp19_;
			_tmp17_ = s;
			_tmp18_ = string_to_string (_tmp17_);
			_tmp19_ = g_strconcat (_tmp18_, "-", NULL);
			_g_free0 (_tmp14_);
			_tmp14_ = _tmp19_;
		}
		_tmp20_ = g_strconcat (_tmp14_, "SYNC", NULL);
		_g_free0 (s);
		s = _tmp20_;
		_g_free0 (_tmp14_);
	}
	if ((GCRY_CIPHER_SECURE & flags) != 0) {
		gchar* _tmp21_ = NULL;
		const gchar* _tmp22_;
		gchar* _tmp27_;
		_tmp22_ = s;
		if (_tmp22_ == NULL) {
			gchar* _tmp23_;
			_tmp23_ = g_strdup ("");
			_g_free0 (_tmp21_);
			_tmp21_ = _tmp23_;
		} else {
			const gchar* _tmp24_;
			const gchar* _tmp25_;
			gchar* _tmp26_;
			_tmp24_ = s;
			_tmp25_ = string_to_string (_tmp24_);
			_tmp26_ = g_strconcat (_tmp25_, "-", NULL);
			_g_free0 (_tmp21_);
			_tmp21_ = _tmp26_;
		}
		_tmp27_ = g_strconcat (_tmp21_, "SECURE", NULL);
		_g_free0 (s);
		s = _tmp27_;
		_g_free0 (_tmp21_);
	}
	_tmp29_ = s;
	_tmp28_ = _tmp29_;
	if (_tmp28_ == NULL) {
		_tmp28_ = "NONE";
	}
	_tmp30_ = g_strdup (_tmp28_);
	result = _tmp30_;
	_g_free0 (s);
	return result;
}

static enum gcry_cipher_flags
crypto_symmetric_cipher_flag_from_string (const gchar* flag_name)
{
	enum gcry_cipher_flags result;
	g_return_val_if_fail (flag_name != NULL, 0);
	if (g_strcmp0 (flag_name, "SECURE") == 0) {
		result = GCRY_CIPHER_SECURE;
		return result;
	}
	if (g_strcmp0 (flag_name, "SYNC") == 0) {
		result = GCRY_CIPHER_ENABLE_SYNC;
		return result;
	}
	if (g_strcmp0 (flag_name, "CTS") == 0) {
		result = GCRY_CIPHER_CBC_CTS;
		return result;
	}
	if (g_strcmp0 (flag_name, "MAC") == 0) {
		result = GCRY_CIPHER_CBC_MAC;
		return result;
	}
	result = 0;
	return result;
}

static enum gcry_cipher_flags
crypto_symmetric_cipher_flags_from_string (const gchar* flag_names)
{
	enum gcry_cipher_flags flags = 0;
	gchar** _tmp0_;
	gchar** _tmp1_;
	enum gcry_cipher_flags result;
	g_return_val_if_fail (flag_names != NULL, 0);
	flags = 0;
	_tmp1_ = _tmp0_ = g_strsplit (flag_names, "-", 0);
	{
		gchar** flag_collection = NULL;
		gint flag_collection_length1 = 0;
		gint _flag_collection_size_ = 0;
		gint flag_it = 0;
		flag_collection = _tmp1_;
		flag_collection_length1 = _vala_array_length (_tmp0_);
		for (flag_it = 0; flag_it < flag_collection_length1; flag_it = flag_it + 1) {
			gchar* _tmp2_;
			gchar* flag = NULL;
			_tmp2_ = g_strdup (flag_collection[flag_it]);
			flag = _tmp2_;
			{
				const gchar* _tmp3_;
				_tmp3_ = flag;
				flags |= crypto_symmetric_cipher_flag_from_string (_tmp3_);
				_g_free0 (flag);
			}
		}
		flag_collection = (_vala_array_free (flag_collection, flag_collection_length1, (GDestroyNotify) g_free), NULL);
	}
	result = flags;
	return result;
}

static gboolean
crypto_symmetric_cipher_parse (const gchar* algo_name,
                               enum gcry_cipher_algos* algo,
                               enum gcry_cipher_modes* mode,
                               enum gcry_cipher_flags* flags)
{
	enum gcry_cipher_algos _vala_algo = 0;
	enum gcry_cipher_modes _vala_mode = 0;
	enum gcry_cipher_flags _vala_flags = 0;
	gchar** algo_parts = NULL;
	gchar** _tmp0_;
	gchar** _tmp1_;
	gint algo_parts_length1;
	gint _algo_parts_size_;
	gchar** _tmp2_;
	gint _tmp2__length1;
	const gchar* _tmp3_;
	gchar** _tmp4_;
	gint _tmp4__length1;
	gchar** _tmp7_;
	gint _tmp7__length1;
	gchar* _tmp10_;
	gchar* _tmp11_;
	gboolean _tmp12_;
	gboolean result;
	g_return_val_if_fail (algo_name != NULL, FALSE);
	_vala_algo = GCRY_CIPHER_NONE;
	_vala_mode = GCRY_CIPHER_MODE_NONE;
	_vala_flags = 0;
	_tmp1_ = _tmp0_ = g_strsplit (algo_name, "-", 3);
	algo_parts = _tmp1_;
	algo_parts_length1 = _vala_array_length (_tmp0_);
	_algo_parts_size_ = algo_parts_length1;
	_tmp2_ = algo_parts;
	_tmp2__length1 = algo_parts_length1;
	_tmp3_ = _tmp2_[0];
	_vala_algo = gcry_cipher_map_name (_tmp3_);
	_tmp4_ = algo_parts;
	_tmp4__length1 = algo_parts_length1;
	if (_tmp4__length1 >= 2) {
		gchar** _tmp5_;
		gint _tmp5__length1;
		const gchar* _tmp6_;
		_tmp5_ = algo_parts;
		_tmp5__length1 = algo_parts_length1;
		_tmp6_ = _tmp5_[1];
		_vala_mode = crypto_symmetric_cipher_mode_from_string (_tmp6_);
	}
	_tmp7_ = algo_parts;
	_tmp7__length1 = algo_parts_length1;
	if (_tmp7__length1 == 3) {
		gchar** _tmp8_;
		gint _tmp8__length1;
		const gchar* _tmp9_;
		_tmp8_ = algo_parts;
		_tmp8__length1 = algo_parts_length1;
		_tmp9_ = _tmp8_[2];
		_vala_flags = _vala_flags | crypto_symmetric_cipher_flags_from_string (_tmp9_);
	}
	_tmp10_ = crypto_symmetric_cipher_to_algo_name (_vala_algo, _vala_mode, _vala_flags);
	_tmp11_ = _tmp10_;
	_tmp12_ = g_strcmp0 (_tmp11_, algo_name) == 0;
	_g_free0 (_tmp11_);
	result = _tmp12_;
	algo_parts = (_vala_array_free (algo_parts, algo_parts_length1, (GDestroyNotify) g_free), NULL);
	if (algo) {
		*algo = _vala_algo;
	}
	if (mode) {
		*mode = _vala_mode;
	}
	if (flags) {
		*flags = _vala_flags;
	}
	return result;
}

static gchar*
crypto_symmetric_cipher_to_algo_name (enum gcry_cipher_algos algo,
                                      enum gcry_cipher_modes mode,
                                      enum gcry_cipher_flags flags)
{
	gchar* result;
	if (flags != 0) {
		const gchar* _tmp0_;
		const gchar* _tmp1_;
		const gchar* _tmp2_;
		gchar* _tmp3_;
		gchar* _tmp4_;
		const gchar* _tmp5_;
		gchar* _tmp6_;
		gchar* _tmp7_;
		_tmp0_ = gcry_cipher_algo_name (algo);
		_tmp1_ = crypto_symmetric_cipher_mode_to_string (mode);
		_tmp2_ = string_to_string (_tmp1_);
		_tmp3_ = crypto_symmetric_cipher_flags_to_string (flags);
		_tmp4_ = _tmp3_;
		_tmp5_ = string_to_string (_tmp4_);
		_tmp6_ = g_strconcat (_tmp0_, "-", _tmp2_, "-", _tmp5_, NULL);
		_tmp7_ = _tmp6_;
		_g_free0 (_tmp4_);
		result = _tmp7_;
		return result;
	} else {
		if (mode != GCRY_CIPHER_MODE_NONE) {
			const gchar* _tmp8_;
			const gchar* _tmp9_;
			const gchar* _tmp10_;
			gchar* _tmp11_;
			_tmp8_ = gcry_cipher_algo_name (algo);
			_tmp9_ = crypto_symmetric_cipher_mode_to_string (mode);
			_tmp10_ = string_to_string (_tmp9_);
			_tmp11_ = g_strconcat (_tmp8_, "-", _tmp10_, NULL);
			result = _tmp11_;
			return result;
		} else {
			const gchar* _tmp12_;
			gchar* _tmp13_;
			_tmp12_ = gcry_cipher_algo_name (algo);
			_tmp13_ = g_strdup (_tmp12_);
			result = _tmp13_;
			return result;
		}
	}
}

CryptoSymmetricCipher*
crypto_symmetric_cipher_construct (GType object_type,
                                   const gchar* algo_name,
                                   GError** error)
{
	CryptoSymmetricCipher* self = NULL;
	enum gcry_cipher_algos algo = 0;
	enum gcry_cipher_modes mode = 0;
	enum gcry_cipher_flags flags = 0;
	enum gcry_cipher_algos _tmp0_ = 0;
	enum gcry_cipher_modes _tmp1_ = 0;
	enum gcry_cipher_flags _tmp2_ = 0;
	gboolean _tmp3_;
	GError* _inner_error0_ = NULL;
	g_return_val_if_fail (algo_name != NULL, NULL);
	_tmp3_ = crypto_symmetric_cipher_parse (algo_name, &_tmp0_, &_tmp1_, &_tmp2_);
	algo = _tmp0_;
	mode = _tmp1_;
	flags = _tmp2_;
	if (_tmp3_) {
		self = (CryptoSymmetricCipher*) crypto_symmetric_cipher_construct_gcrypt (object_type, algo, mode, flags, &_inner_error0_);
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (_inner_error0_->domain == CRYPTO_ERROR) {
				g_propagate_error (error, _inner_error0_);
				_crypto_symmetric_cipher_unref0 (self);
				return NULL;
			} else {
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return NULL;
			}
		}
	} else {
		const gchar* _tmp4_;
		gchar* _tmp5_;
		gchar* _tmp6_;
		GError* _tmp7_;
		GError* _tmp8_;
		_tmp4_ = string_to_string (algo_name);
		_tmp5_ = g_strconcat ("The algorithm ", _tmp4_, " is not supported", NULL);
		_tmp6_ = _tmp5_;
		_tmp7_ = g_error_new_literal (CRYPTO_ERROR, CRYPTO_ERROR_ILLEGAL_ARGUMENTS, _tmp6_);
		_tmp8_ = _tmp7_;
		_g_free0 (_tmp6_);
		_inner_error0_ = _tmp8_;
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			_crypto_symmetric_cipher_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	return self;
}

CryptoSymmetricCipher*
crypto_symmetric_cipher_new (const gchar* algo_name,
                             GError** error)
{
	return crypto_symmetric_cipher_construct (CRYPTO_TYPE_SYMMETRIC_CIPHER, algo_name, error);
}

static CryptoSymmetricCipher*
crypto_symmetric_cipher_construct_gcrypt (GType object_type,
                                          enum gcry_cipher_algos algo,
                                          enum gcry_cipher_modes mode,
                                          enum gcry_cipher_flags flags,
                                          GError** error)
{
	CryptoSymmetricCipher* self = NULL;
	gcry_cipher_hd_t _tmp0_ = {0};
	gcry_error_t _tmp1_;
	GError* _inner_error0_ = NULL;
	self = (CryptoSymmetricCipher*) g_type_create_instance (object_type);
	_tmp1_ = gcry_cipher_open (&_tmp0_, algo, mode, flags);
	self->priv->cipher = _tmp0_;
	crypto_may_throw_gcrypt_error (_tmp1_, &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			_crypto_symmetric_cipher_unref0 (self);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	return self;
}

static CryptoSymmetricCipher*
crypto_symmetric_cipher_new_gcrypt (enum gcry_cipher_algos algo,
                                    enum gcry_cipher_modes mode,
                                    enum gcry_cipher_flags flags,
                                    GError** error)
{
	return crypto_symmetric_cipher_construct_gcrypt (CRYPTO_TYPE_SYMMETRIC_CIPHER, algo, mode, flags, error);
}

void
crypto_symmetric_cipher_set_key (CryptoSymmetricCipher* self,
                                 guint8* key,
                                 gint key_length1,
                                 GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_setkey (self->priv->cipher, key, (gint) key_length1), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

void
crypto_symmetric_cipher_set_iv (CryptoSymmetricCipher* self,
                                guint8* iv,
                                gint iv_length1,
                                GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_setiv (self->priv->cipher, iv, (gint) iv_length1), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

void
crypto_symmetric_cipher_set_counter_vector (CryptoSymmetricCipher* self,
                                            guint8* ctr,
                                            gint ctr_length1,
                                            GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_setctr (self->priv->cipher, ctr, (gint) ctr_length1), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

void
crypto_symmetric_cipher_reset (CryptoSymmetricCipher* self,
                               GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_reset (self->priv->cipher), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

guint8*
crypto_symmetric_cipher_get_tag (CryptoSymmetricCipher* self,
                                 gsize taglen,
                                 gint* result_length1,
                                 GError** error)
{
	guint8* tag = NULL;
	guint8* _tmp0_;
	gint tag_length1;
	gint _tag_size_;
	guint8* _tmp1_;
	gint _tmp1__length1;
	GError* _inner_error0_ = NULL;
	guint8* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_new0 (guint8, taglen);
	tag = _tmp0_;
	tag_length1 = taglen;
	_tag_size_ = tag_length1;
	crypto_may_throw_gcrypt_error (gcry_cipher_gettag (self->priv->cipher, tag, (gint) tag_length1), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			tag = (g_free (tag), NULL);
			return NULL;
		} else {
			tag = (g_free (tag), NULL);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	_tmp1_ = tag;
	_tmp1__length1 = tag_length1;
	if (result_length1) {
		*result_length1 = _tmp1__length1;
	}
	result = _tmp1_;
	return result;
}

void
crypto_symmetric_cipher_check_tag (CryptoSymmetricCipher* self,
                                   guint8* tag,
                                   gint tag_length1,
                                   GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_checktag (self->priv->cipher, tag, (gint) tag_length1), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

void
crypto_symmetric_cipher_encrypt (CryptoSymmetricCipher* self,
                                 guint8* output,
                                 gint output_length1,
                                 guint8* input,
                                 gint input_length1,
                                 GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_encrypt (self->priv->cipher, output, (gint) output_length1, input, (gint) input_length1), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

void
crypto_symmetric_cipher_decrypt (CryptoSymmetricCipher* self,
                                 guint8* output,
                                 gint output_length1,
                                 guint8* input,
                                 gint input_length1,
                                 GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_decrypt (self->priv->cipher, output, (gint) output_length1, input, (gint) input_length1), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

void
crypto_symmetric_cipher_sync (CryptoSymmetricCipher* self,
                              GError** error)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	crypto_may_throw_gcrypt_error (gcry_cipher_sync (self->priv->cipher), &_inner_error0_);
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == CRYPTO_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
}

static void
crypto_value_symmetric_cipher_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
crypto_value_symmetric_cipher_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		crypto_symmetric_cipher_unref (value->data[0].v_pointer);
	}
}

static void
crypto_value_symmetric_cipher_copy_value (const GValue* src_value,
                                          GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = crypto_symmetric_cipher_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
crypto_value_symmetric_cipher_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
crypto_value_symmetric_cipher_collect_value (GValue* value,
                                             guint n_collect_values,
                                             GTypeCValue* collect_values,
                                             guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		CryptoSymmetricCipher * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = crypto_symmetric_cipher_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
crypto_value_symmetric_cipher_lcopy_value (const GValue* value,
                                           guint n_collect_values,
                                           GTypeCValue* collect_values,
                                           guint collect_flags)
{
	CryptoSymmetricCipher ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = crypto_symmetric_cipher_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
crypto_param_spec_symmetric_cipher (const gchar* name,
                                    const gchar* nick,
                                    const gchar* blurb,
                                    GType object_type,
                                    GParamFlags flags)
{
	CryptoParamSpecSymmetricCipher* spec;
	g_return_val_if_fail (g_type_is_a (object_type, CRYPTO_TYPE_SYMMETRIC_CIPHER), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
crypto_value_get_symmetric_cipher (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, CRYPTO_TYPE_SYMMETRIC_CIPHER), NULL);
	return value->data[0].v_pointer;
}

void
crypto_value_set_symmetric_cipher (GValue* value,
                                   gpointer v_object)
{
	CryptoSymmetricCipher * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, CRYPTO_TYPE_SYMMETRIC_CIPHER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, CRYPTO_TYPE_SYMMETRIC_CIPHER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		crypto_symmetric_cipher_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		crypto_symmetric_cipher_unref (old);
	}
}

void
crypto_value_take_symmetric_cipher (GValue* value,
                                    gpointer v_object)
{
	CryptoSymmetricCipher * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, CRYPTO_TYPE_SYMMETRIC_CIPHER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, CRYPTO_TYPE_SYMMETRIC_CIPHER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		crypto_symmetric_cipher_unref (old);
	}
}

static void
crypto_symmetric_cipher_class_init (CryptoSymmetricCipherClass * klass,
                                    gpointer klass_data)
{
	crypto_symmetric_cipher_parent_class = g_type_class_peek_parent (klass);
	((CryptoSymmetricCipherClass *) klass)->finalize = crypto_symmetric_cipher_finalize;
	g_type_class_adjust_private_offset (klass, &CryptoSymmetricCipher_private_offset);
}

static void
crypto_symmetric_cipher_instance_init (CryptoSymmetricCipher * self,
                                       gpointer klass)
{
	self->priv = crypto_symmetric_cipher_get_instance_private (self);
	self->ref_count = 1;
}

static void
crypto_symmetric_cipher_finalize (CryptoSymmetricCipher * obj)
{
	CryptoSymmetricCipher * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, CRYPTO_TYPE_SYMMETRIC_CIPHER, CryptoSymmetricCipher);
	g_signal_handlers_destroy (self);
}

static GType
crypto_symmetric_cipher_get_type_once (void)
{
	static const GTypeValueTable g_define_type_value_table = { crypto_value_symmetric_cipher_init, crypto_value_symmetric_cipher_free_value, crypto_value_symmetric_cipher_copy_value, crypto_value_symmetric_cipher_peek_pointer, "p", crypto_value_symmetric_cipher_collect_value, "p", crypto_value_symmetric_cipher_lcopy_value };
	static const GTypeInfo g_define_type_info = { sizeof (CryptoSymmetricCipherClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) crypto_symmetric_cipher_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (CryptoSymmetricCipher), 0, (GInstanceInitFunc) crypto_symmetric_cipher_instance_init, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	GType crypto_symmetric_cipher_type_id;
	crypto_symmetric_cipher_type_id = g_type_register_fundamental (g_type_fundamental_next (), "CryptoSymmetricCipher", &g_define_type_info, &g_define_type_fundamental_info, 0);
	CryptoSymmetricCipher_private_offset = g_type_add_instance_private (crypto_symmetric_cipher_type_id, sizeof (CryptoSymmetricCipherPrivate));
	return crypto_symmetric_cipher_type_id;
}

GType
crypto_symmetric_cipher_get_type (void)
{
	static volatile gsize crypto_symmetric_cipher_type_id__once = 0;
	if (g_once_init_enter (&crypto_symmetric_cipher_type_id__once)) {
		GType crypto_symmetric_cipher_type_id;
		crypto_symmetric_cipher_type_id = crypto_symmetric_cipher_get_type_once ();
		g_once_init_leave (&crypto_symmetric_cipher_type_id__once, crypto_symmetric_cipher_type_id);
	}
	return crypto_symmetric_cipher_type_id__once;
}

gpointer
crypto_symmetric_cipher_ref (gpointer instance)
{
	CryptoSymmetricCipher * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
crypto_symmetric_cipher_unref (gpointer instance)
{
	CryptoSymmetricCipher * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		CRYPTO_SYMMETRIC_CIPHER_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

static gssize
_vala_array_length (gpointer array)
{
	gssize length;
	length = 0;
	if (array) {
		while (((gpointer*) array)[length]) {
			length++;
		}
	}
	return length;
}

