/*
 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
 * All rights reserved.
 * Redistribution and modifications are permitted subject to BSD license.
 */
#ifndef ASN_DISABLE_OER_SUPPORT

#include <asn_internal.h>
#include <INTEGER.h>
#include <errno.h>

asn_dec_rval_t
INTEGER_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
                   const asn_oer_constraints_t *constraints, void **sptr,
                   const void *ptr, size_t size) {
    const asn_INTEGER_specifics_t *specs =
        (const asn_INTEGER_specifics_t *)td->specifics;
    asn_dec_rval_t rval = {RC_OK, 0};
    INTEGER_t *st = (INTEGER_t *)*sptr;
    struct asn_oer_constraint_number_s ct = {0, 0};
    size_t req_bytes;

    (void)opt_codec_ctx;
    (void)specs;

    if(!st) {
        st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
        if(!st) ASN__DECODE_FAILED;
    }

    FREEMEM(st->buf);
    st->buf = 0;
    st->size = 0;

    if(!constraints) constraints = td->encoding_constraints.oer_constraints;
    if(constraints) ct = constraints->value;

    if(ct.width) {
        req_bytes = ct.width;
    } else {
        /* No lower bound and no upper bound, effectively */

        ssize_t consumed = oer_fetch_length(ptr, size, &req_bytes);
        if(consumed == 0) {
            ASN__DECODE_STARVED;
        } else if(consumed == -1) {
            ASN__DECODE_FAILED;
        }
        rval.consumed += consumed;
        ptr = (const char *)ptr + consumed;
        size -= consumed;
    }

    if(req_bytes > size) {
        ASN__DECODE_STARVED;
    }

    if(ct.positive) {
        /* X.969 08/2015 10.2(a) */
        unsigned msb;   /* Most significant bit */
        size_t useful_size;

        /* Check most significant bit */
        msb = *(const uint8_t *)ptr >> 7; /* yields 0 or 1 */
        useful_size = msb + req_bytes;
        st->buf = (uint8_t *)MALLOC(useful_size + 1);
        if(!st->buf) {
            ASN__DECODE_FAILED;
        }

        /*
         * Record a large unsigned in a way not to confuse it
         * with signed value.
         */
        st->buf[0] = '\0';
        memcpy(st->buf + msb, ptr, req_bytes);
        st->buf[useful_size] = '\0';    /* Just in case, 0-terminate */
        st->size = useful_size;

        rval.consumed += req_bytes;
        return rval;
    } else {
        /* X.969 08/2015 10.2(b) */
        st->buf = (uint8_t *)MALLOC(req_bytes + 1);
        if(!st->buf) {
            ASN__DECODE_FAILED;
        }

        memcpy(st->buf, ptr, req_bytes);
        st->buf[req_bytes] = '\0'; /* Just in case, 0-terminate */
        st->size = req_bytes;

        rval.consumed += req_bytes;
        return rval;
    }
}

/*
 * Encode as Canonical OER.
 */
asn_enc_rval_t
INTEGER_encode_oer(asn_TYPE_descriptor_t *td,
                   const asn_oer_constraints_t *constraints, void *sptr,
                   asn_app_consume_bytes_f *cb, void *app_key) {
    const INTEGER_t *st = sptr;
    asn_enc_rval_t er;
    struct asn_oer_constraint_number_s ct = {0, 0};
    const uint8_t *buf;
    const uint8_t *end;
    size_t useful_bytes;
    size_t req_bytes = 0;
    int sign = 0;

    if(!st || st->size == 0) ASN__ENCODE_FAILED;

    if(!constraints) constraints = td->encoding_constraints.oer_constraints;
    if(constraints) ct = constraints->value;

    er.encoded = 0;

    buf = st->buf;
    end = buf + st->size;

    sign = (buf && buf < end) ? buf[0] & 0x80 : 0;

    /* Ignore 9 leading zeroes or ones */
    if(ct.positive) {
        if(sign) {
            /* The value given is a signed value. Can't proceed. */
            ASN__ENCODE_FAILED;
        }
        /* Remove leading zeros. */
        for(; buf + 1 < end; buf++) {
            if(buf[0] != 0x0) break;
        }
    } else {
        for(; buf + 1 < end; buf++) {
            if(buf[0] == 0x0 && (buf[1] & 0x80) == 0) {
                continue;
            } else if(buf[0] == 0xff && (buf[1] & 0x80) != 0) {
                continue;
            }
            break;
        }
    }

    useful_bytes = end - buf;
    if(ct.width) {
        req_bytes = ct.width;
    } else {
        ssize_t r = oer_serialize_length(useful_bytes, cb, app_key);
        if(r < 0) {
            ASN__ENCODE_FAILED;
        }
        er.encoded += r;
        req_bytes = useful_bytes;
    }

    if(req_bytes < useful_bytes) {
        ASN__ENCODE_FAILED;
    }

    er.encoded += req_bytes;

    for(; req_bytes > useful_bytes; req_bytes--) {
        if(cb(sign?"\xff":"\0", 1, app_key) < 0) {
            ASN__ENCODE_FAILED;
        }
    }

    if(cb(buf, useful_bytes, app_key) < 0) {
        ASN__ENCODE_FAILED;
    }

    ASN__ENCODED_OK(er);
}

#endif  /* ASN_DISABLE_OER_SUPPORT */
