#ifndef RBUF_RBUF_H_
#define RBUF_RBUF_H_

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

typedef struct {
  uint8_t *buffer;
  size_t tail;
  size_t head;
  size_t cap;
  size_t count;
  bool full;
} RBuf;

int32_t rbuf_push(RBuf *rbuf, uint8_t data);
int32_t rbuf_pop(RBuf *rbuf, uint8_t *data);
void rbuf_init(RBuf *rbuf, uint8_t *buf, size_t bufsize);

typedef struct {
  uint8_t *buffer;
  size_t tail;
  size_t head;
  size_t cap;
  size_t count;
  bool full;
  size_t typesize;
} RBufT;

#define rbuft_init(rbt, tbuf, ts, nmax) do { \
    rbuf_init((RBuf *)(rbt), (uint8_t *)(tbuf), (ts) * (nmax)); \
    (rbt)->typesize = (ts); \
  } while (0)

#define rbuft_push(rbt, data1) \
  do { \
    uint8_t *__data = (uint8_t *)(data1); \
    for (size_t __i = 0; __i < (rbt)->typesize; __i++) { \
      rbuf_push((RBuf *)(rbt), __data[__i]); \
    } \
  } while(0)

#define rbuft_pop(rbt, out1, emptyb) \
  do { \
    uint8_t *__out = (uint8_t *)(out1); \
    for (size_t __i = 0; __i < (rbt)->typesize; __i++) { \
      if (rbuf_pop((RBuf *)(rbt), &__out[__i]) < 0) { \
        *(emptyb) = true; \
      } \
    } \
  } while(0)

#endif // RBUF_RBUF_H_
