/*
 * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
 * From ASN.1 module "SABP-IEs"
 * 	found in "../../asn1/sabp/SABP-IEs.asn"
 */

#include <osmocom/sabp/SABP_Data-Coding-Scheme.h>

int
SABP_Data_Coding_Scheme_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
	size_t size;
	
	if(!sptr) {
		_ASN_CTFAIL(app_key, td, sptr,
			"%s: value not given (%s:%d)",
			td->name, __FILE__, __LINE__);
		return -1;
	}
	
	if(st->size > 0) {
		/* Size in bits */
		size = 8 * st->size - (st->bits_unused & 0x07);
	} else {
		size = 0;
	}
	
	if((size == 8l)) {
		/* Constraint check succeeded */
		return 0;
	} else {
		_ASN_CTFAIL(app_key, td, sptr,
			"%s: constraint failed (%s:%d)",
			td->name, __FILE__, __LINE__);
		return -1;
	}
}

/*
 * This type is implemented using BIT_STRING,
 * so here we adjust the DEF accordingly.
 */
static void
SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
	td->free_struct    = asn_DEF_BIT_STRING.free_struct;
	td->print_struct   = asn_DEF_BIT_STRING.print_struct;
	td->check_constraints = asn_DEF_BIT_STRING.check_constraints;
	td->ber_decoder    = asn_DEF_BIT_STRING.ber_decoder;
	td->der_encoder    = asn_DEF_BIT_STRING.der_encoder;
	td->xer_decoder    = asn_DEF_BIT_STRING.xer_decoder;
	td->xer_encoder    = asn_DEF_BIT_STRING.xer_encoder;
	td->uper_decoder   = asn_DEF_BIT_STRING.uper_decoder;
	td->uper_encoder   = asn_DEF_BIT_STRING.uper_encoder;
	td->aper_decoder   = asn_DEF_BIT_STRING.aper_decoder;
	td->aper_encoder   = asn_DEF_BIT_STRING.aper_encoder;
	if(!td->per_constraints)
		td->per_constraints = asn_DEF_BIT_STRING.per_constraints;
	td->elements       = asn_DEF_BIT_STRING.elements;
	td->elements_count = asn_DEF_BIT_STRING.elements_count;
	td->specifics      = asn_DEF_BIT_STRING.specifics;
}

void
SABP_Data_Coding_Scheme_free(asn_TYPE_descriptor_t *td,
		void *struct_ptr, int contents_only) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	td->free_struct(td, struct_ptr, contents_only);
}

int
SABP_Data_Coding_Scheme_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
}

asn_dec_rval_t
SABP_Data_Coding_Scheme_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		void **structure, const void *bufptr, size_t size, int tag_mode) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}

asn_enc_rval_t
SABP_Data_Coding_Scheme_encode_der(asn_TYPE_descriptor_t *td,
		void *structure, int tag_mode, ber_tlv_tag_t tag,
		asn_app_consume_bytes_f *cb, void *app_key) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}

asn_dec_rval_t
SABP_Data_Coding_Scheme_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
}

asn_enc_rval_t
SABP_Data_Coding_Scheme_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
		int ilevel, enum xer_encoder_flags_e flags,
		asn_app_consume_bytes_f *cb, void *app_key) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
}

asn_dec_rval_t
SABP_Data_Coding_Scheme_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}

asn_enc_rval_t
SABP_Data_Coding_Scheme_encode_uper(asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints,
		void *structure, asn_per_outp_t *per_out) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->uper_encoder(td, constraints, structure, per_out);
}

asn_enc_rval_t
SABP_Data_Coding_Scheme_encode_aper(asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints,
		void *structure, asn_per_outp_t *per_out) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->aper_encoder(td, constraints, structure, per_out);
}

asn_dec_rval_t
SABP_Data_Coding_Scheme_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
	SABP_Data_Coding_Scheme_1_inherit_TYPE_descriptor(td);
	return td->aper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}

static asn_per_constraints_t asn_PER_type_SABP_Data_Coding_Scheme_constr_1 GCC_NOTUSED = {
	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
	{ APC_CONSTRAINED,	 0,  0,  8l,  8l }	/* (SIZE(8..8)) */,
	0, 0	/* No PER value map */
};
static const ber_tlv_tag_t asn_DEF_SABP_Data_Coding_Scheme_tags_1[] = {
	(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
};
asn_TYPE_descriptor_t asn_DEF_SABP_Data_Coding_Scheme = {
	"SABP_Data-Coding-Scheme",
	"SABP_Data-Coding-Scheme",
	SABP_Data_Coding_Scheme_free,
	SABP_Data_Coding_Scheme_print,
	SABP_Data_Coding_Scheme_constraint,
	SABP_Data_Coding_Scheme_decode_ber,
	SABP_Data_Coding_Scheme_encode_der,
	SABP_Data_Coding_Scheme_decode_xer,
	SABP_Data_Coding_Scheme_encode_xer,
	SABP_Data_Coding_Scheme_decode_uper,
	SABP_Data_Coding_Scheme_encode_uper,
	SABP_Data_Coding_Scheme_decode_aper,
	SABP_Data_Coding_Scheme_encode_aper,
	0,	/* Use generic outmost tag fetcher */
	asn_DEF_SABP_Data_Coding_Scheme_tags_1,
	sizeof(asn_DEF_SABP_Data_Coding_Scheme_tags_1)
		/sizeof(asn_DEF_SABP_Data_Coding_Scheme_tags_1[0]), /* 1 */
	asn_DEF_SABP_Data_Coding_Scheme_tags_1,	/* Same as above */
	sizeof(asn_DEF_SABP_Data_Coding_Scheme_tags_1)
		/sizeof(asn_DEF_SABP_Data_Coding_Scheme_tags_1[0]), /* 1 */
	&asn_PER_type_SABP_Data_Coding_Scheme_constr_1,
	0, 0,	/* No members */
	0	/* No specifics */
};

