Buffer :: struct {
   allocator: Allocator;

   data:  [..]u8;
   count: int;
}

append :: inline (buf: *Buffer, ptr: *void, count: int) {
   free_space := ensure_buffer_has_room(buf, count);
   memcpy(free_space, ptr, count);
   buf.count += count;
}

append :: inline (buf: *Buffer, data: []u8) {
   append(buf, data.data, data.count);
}

append :: inline (buf: *Buffer, ptr: *$T) {
   append(buf, ptr, size_of(T));
}

reset :: inline (buf: *Buffer) {
   buf.count = 0;
}

#scope_file;

array :: #import "jc/array";

ensure_buffer_has_room :: (buf: *Buffer, count: int) -> *u8 {
   ptr := buf.data.data + buf.count;
   if buf.count + count >= buf.data.allocated {
      array.resize(*buf.data, buf.data.allocated * 2);
      ptr = buf.data.data + buf.count;
      buf.data.count = buf.data.allocated;
   }

   return ptr;
}

#if RUN_TESTS #run {
   test.run("basic operations", t => {
      buf: Buffer;
   });
}
