// The growable container of the prelude. Consumers never import this file
// directly — std.sx re-exports `List`.
#import "modules/std/core.sx";

List :: struct ($T: Type) {
    items: [*]T = null;
    len: i64 = 0;
    cap: i64 = 0;

    append :: (list: *List(T), item: T, alloc: Allocator = context.allocator) {
        if list.len >= list.cap {
            new_cap := if list.cap == 0 then 4 else list.cap * 2;
            new_items : [*]T = xx alloc.alloc_bytes(new_cap * size_of(T));
            if list.len > 0 {
                memcpy(new_items, list.items, list.len * size_of(T));
                alloc.dealloc_bytes(list.items);
            }
            list.items = new_items;
            list.cap = new_cap;
        }
        list.items[list.len] = item;
        list.len += 1;
    }

    ensure_capacity :: (list: *List(T), n: i64, alloc: Allocator = context.allocator) {
        if list.cap >= n { return; }
        new_cap := if list.cap == 0 then 4 else list.cap;
        while new_cap < n { new_cap = new_cap * 2; }
        new_items : [*]T = xx alloc.alloc_bytes(new_cap * size_of(T));
        if list.len > 0 {
            memcpy(new_items, list.items, list.len * size_of(T));
            alloc.dealloc_bytes(list.items);
        }
        list.items = new_items;
        list.cap = new_cap;
    }

    deinit :: (list: *List(T), alloc: Allocator = context.allocator) {
        if list.items != null {
            alloc.dealloc_bytes(list.items);
        }
        list.items = null;
        list.len = 0;
        list.cap = 0;
    }
}
