/*
 * 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 <constr_SET_OF.h>
#include <asn_SET_OF.h>
#include <errno.h>

/*
 * This macro "eats" the part of the buffer which is definitely "consumed",
 * i.e. was correctly converted into local representation or rightfully skipped.
 */
#undef  ADVANCE
#define ADVANCE(num_bytes)                   \
    do {                                     \
        size_t num = num_bytes;              \
        ptr = ((const char *)ptr) + num;     \
        size -= num;                         \
        consumed_myself += num;              \
    } while(0)

/*
 * Switch to the next phase of parsing.
 */
#undef  NEXT_PHASE
#define NEXT_PHASE(ctx) \
    do {                \
        ctx->phase++;   \
        ctx->step = 0;  \
    } while(0)
#undef  SET_PHASE
#define SET_PHASE(ctx, value) \
    do {                      \
        ctx->phase = value;   \
        ctx->step = 0;        \
    } while(0)

/*
 * Return a standardized complex structure.
 */
#undef  RETURN
#define RETURN(_code)                    \
    do {                                 \
        asn_dec_rval_t rval;             \
        rval.code = _code;               \
        rval.consumed = consumed_myself; \
        return rval;                     \
    } while(0)

/*
 * The SEQUENCE OF and SET OF values utilize a "quantity field".
 * It is is a pointless combination of #8.6 (length determinant, capable
 * of encoding tiny and huge numbers in the shortest possible number of octets)
 * and the variable sized integer. What could have been encoded by #8.6 alone
 * is required to be encoded by #8.6 followed by that number of unsigned octets.
 * This doesn't make too much sense. It seems that the original version of OER
 * standard have been using the unconstrained unsigned integer as a quantity
 * field, and this legacy have gone through ISO/ITU-T standardization process.
 */
static ssize_t
oer_fetch_quantity(const void *ptr, size_t size, size_t *qty_r) {
    const uint8_t *b;
    const uint8_t *bend;
    size_t len = 0;
    size_t qty;

    ssize_t len_len = oer_fetch_length(ptr, size, &len);
    if(len_len <= 0) {
        *qty_r = 0;
        return len_len;
    }

    if((len_len + len) > size) {
        *qty_r = 0;
        return 0;
    }

    b = (const uint8_t *)ptr + len_len;
    bend = b + len;

    /* Skip the leading 0-bytes */
    for(; b < bend && *b == 0; b++) {
    }

    if((bend - b) > (ssize_t)sizeof(size_t)) {
        /* Length is not representable by the native size_t type */
        *qty_r = 0;
        return -1;
    }

    for(qty = 0; b < bend; b++) {
        qty = (qty << 8) + *b;
    }

    if(qty > RSIZE_MAX) { /* A bit of C11 validation */
        *qty_r = 0;
        return -1;
    }

    *qty_r = qty;
    assert((size_t)len_len + len == (size_t)(bend - (const uint8_t *)ptr));
    return len_len + len;
}

asn_dec_rval_t
SET_OF_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
                    const asn_oer_constraints_t *constraints, void **struct_ptr,
                    const void *ptr, size_t size) {
    asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
    asn_dec_rval_t rval = {RC_OK, 0};
    void *st = *struct_ptr; /* Target structure */
    asn_struct_ctx_t *ctx; /* Decoder context */
    size_t consumed_myself = 0; /* Consumed bytes from ptr. */

    (void)opt_codec_ctx;
    (void)constraints;

    /*
     * Create the target structure if it is not present already.
     */
    if(st == 0) {
        st = *struct_ptr = CALLOC(1, specs->struct_size);
        if(st == 0) {
            RETURN(RC_FAIL);
        }
    }

    /*
     * Restore parsing context.
     */
    ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);

    /*
     * Start to parse where left previously.
     */
    switch(ctx->phase) {
    case 0: {
        /*
         * Fetch number of elements to decode.
         */
        size_t length = 0;
        size_t len_size = oer_fetch_quantity(ptr, size, &length);
        switch(len_size) {
        case 0:
            RETURN(RC_WMORE);
        case -1:
            RETURN(RC_FAIL);
        default:
    ASN_DEBUG("ptr[] = %02x, advancing %zu, length=%zu", *(const uint8_t *)ptr, len_size, length);
            ADVANCE(len_size);
            ctx->left = length;
        }
    }
        NEXT_PHASE(ctx);
        /* FALL THROUGH */
    case 1: {
        /* Decode components of the extension root */
        asn_TYPE_member_t *elm = td->elements;
        asn_anonymous_set_ *list = _A_SET_FROM_VOID(st);

        assert(td->elements_count == 1);

        ASN_DEBUG("OER SET OF %s Decoding PHASE 1", td->name);

        for(; ctx->left > 0; ctx->left--) {
            asn_dec_rval_t rv = elm->type->op->oer_decoder(
                opt_codec_ctx, elm->type,
                elm->encoding_constraints.oer_constraints, &ctx->ptr, ptr,
                size);
            ADVANCE(rv.consumed);
            switch(rv.code) {
            case RC_OK:
                if(ASN_SET_ADD(list, ctx->ptr) != 0) {
                    RETURN(RC_FAIL);
                } else {
                    ctx->ptr = 0;
                    break;
                }
            case RC_WMORE:
                RETURN(RC_WMORE);
            case RC_FAIL:
                ASN_STRUCT_FREE(*elm->type, ctx->ptr);
                ctx->ptr = 0;
                SET_PHASE(ctx, 3);
                RETURN(RC_FAIL);
            }
        }
        /* Decoded decently. */
        NEXT_PHASE(ctx);
    }
        /* Fall through */
    case 2:
        /* Ignore fully decoded */
        assert(ctx->left == 0);
        RETURN(RC_OK);
    case 3:
        /* Failed to decode. */
        RETURN(RC_FAIL);
    }

    return rval;
}

static ssize_t
oer_put_quantity(size_t qty, asn_app_consume_bytes_f *cb, void *app_key) {
    uint8_t buf[1 + sizeof(size_t)];
    uint8_t *b = &buf[sizeof(size_t)]; /* Last addressable */
    size_t encoded;

    do {
        *b-- = qty;
        qty >>= 8;
    } while(qty);

    *b = sizeof(buf) - (b-buf) - 1;
    encoded = sizeof(buf) - (b-buf);
    if(cb(b, encoded, app_key) < 0)
        return -1;
    return encoded;
}

/*
 * Encode as Canonical OER.
 */
asn_enc_rval_t
SET_OF_encode_oer(asn_TYPE_descriptor_t *td,
                    const asn_oer_constraints_t *constraints, void *sptr,
                    asn_app_consume_bytes_f *cb, void *app_key) {
    size_t computed_size = 0;
    ssize_t qty_len;
    asn_TYPE_member_t *elm;
    asn_anonymous_set_ *list;
    int n;

    (void)constraints;

    if(!sptr) ASN__ENCODE_FAILED;

    elm = td->elements;
    list = _A_SET_FROM_VOID(sptr);

    qty_len = oer_put_quantity(list->count, cb, app_key);
    if(qty_len < 0) {
        ASN__ENCODE_FAILED;
    }
    computed_size += qty_len;

    for(n = 0; n < list->count; n++) {
        void *memb_ptr = list->array[n];
        asn_enc_rval_t er;
        er = elm->type->op->oer_encoder(
            elm->type, elm->encoding_constraints.oer_constraints, memb_ptr, cb,
            app_key);
        if(er.encoded < 0) {
            return er;
        } else {
            computed_size += er.encoded;
        }
    }

    {
        asn_enc_rval_t erval;
        erval.encoded = computed_size;
        ASN__ENCODED_OK(erval);
    }
}

#endif  /* ASN_DISABLE_OER_SUPPORT */
