/*
 * 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->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->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 */
