
int read_int(void *stream, int len, int32_t *out)
{
    if (len < 4)
        return -1;
    *out = (stream[0] << 24)
         | (stream[1] << 16)
         | (stream[2] <<  8)
         | (stream[3] <<  0);
    return 4;
}

#define DO_PARSE(fun, stream, len, pos, var) \
    do {                                                               \
        int res = (fun)((stream) + (pos), (len) - (pos), (var));       \
        if (res < 0)                                                   \
            return -1;                                                 \
        (pos) += res;                                                  \
    } while (0)                                                        \

int decode(void *desc, int dlen, void *_stream, int len)
{
    uint8_t stream = _stream;
    int pos = 0, dpos = 0;

    while (pos < len) {
        switch (desc[dpos++]) {
            int32_t i;
            double f;

          case NUM_INT32:
            DO_PARSE(read_int, stream, len, pos, &i);
            // do sth with i
            break;
        }
        if (dlen == dpos) {
            dpos = 0;
        }
    }
}
