enum {
  WAIT_MAGIC0,
  WAIT_MAGIC1,
  WAIT_HEADER,
  WAIT_PAYLOAD,
  DONE,
} state;

struct packet {
  uint8_t id;
  uint8_t length;
  uint8_t seq_num;
  uint8_t payload[231];
}

// return the size of the consumed data.
size_t parse_packet(uint8_t* data, size_t length, state *state, packet *packet) {
  size_t idx = 0;
  while (idx < length) {
    switch (*state) {
      WAIT_MAGIC0:
        if (data[idx] == 0xab) {
          *state = WAIT_MAGIC1;
        }
        idx++;
        break;

      WAIT_MAGIC1:
        if (data[idx] == 0xba) {
          *state = WAIT_HEADER;
        } else {
          *state = WAIT_MAGIC0;
        }
        idx++;
        break;

      WAIT_HEADER:
        if (idx + 3 >= length) {
          return idx;
        }

        memcpy(packet, data + idx, 3);
        idx += 3;
        *state = WAIT_PAYLOAD;
        break;

      WAIT_PAYLOAD:
        if (idx + packet->length >= length) {
          return idx;
        }

        memcpy(packet->payload, data + idx, packet->length);
        idx += packet->length;
        *state = DONE;
        return idx;
    }
  }

  return idx;
}


int main() {
  uint8_t buf[MAX_PACKET_LEN * 3];
  size_t buf_size = 0;

  state state = WAIT_MAGIC0;
  packet packet;

  while (1) {
    size_t rcv_len = uart_read(); // recieve buffer and store to (buf + buf_size)
    buf_size += rcv_len;

    size_t consumed_len = parse_packet(buf, buf_size, &state, &packet);
    if (state == DONE) {
      // you get a packet.
    } else {
      // remove the consumed buffers.
    }

  }
}
