
use mem

class StructArray[T] {
    ~ size: uint
    ~ data: ptr

    static fn new(start_size: uint (2)) SELF {
        if start_size < 2 {
            start_size = 2
        }
        return SELF {
            size: start_size
            data: mem:calloc(start_size * size_of(<T>))
        }
    }

    fn get(index: uint) T {
        let size = this.size
        if index >= size {
            let new_size = size * 2
            if index >= new_size : new_size = index + 1
            this.increase_size(new_size)
        }
        return @offset(this.data, u8, index * size_of(<T>)).@cast(T)
    }

    fn increase_size(new_size: uint) ptr {
        let data = this.data
        let size = this.size
        if size >= new_size : return data

        // let new_total = new_size * size_of(<T>)
        // let copy_size = size * size_of(<T>)
        // let new_data = mem:resize(this.data, copy_size, new_total)
        let new_total = new_size * size_of(<T>)
        let new_data = mem:alloc(new_total)
        let copy_size = size * size_of(<T>)
        mem:copy(data, new_data, copy_size)
        mem:clear(@offset(new_data, u8, copy_size), new_total - copy_size)
        mem:free(data)

        this.data = new_data
        this.size = new_size
        return new_data
    }

    fn each_get(index: uint) T !end {
        if index >= this.size : throw end
        let v = this.get(index)
        return v
    }

    fn gc_free() {
        mem:free(this.data)
    }
}
