//! Typed vector backed by caller-owned static storage.

/// Typed vector metadata backed by caller-owned storage.
export record Vec⟨T⟩ {
    /// Typed slice containing the vector's storage.
    data: *mut [T],
    /// Number of initialized elements.
    len: u32,
}

/// Initialize a vector over caller-owned storage.
export fn init⟨T⟩(vec: *mut Vec⟨T⟩, arena: *mut [T]) {
    set vec.data = arena;
    set vec.len = 0;
}

/// Return the number of initialized elements.
export fn len⟨T⟩(vec: *Vec⟨T⟩) -> u32 {
    return vec.len;
}

/// Return the storage capacity in elements.
export fn capacity⟨T⟩(vec: *Vec⟨T⟩) -> u32 {
    return vec.data.len;
}

/// Reset a vector without clearing its storage.
export fn reset⟨T⟩(vec: *mut Vec⟨T⟩) {
    set vec.len = 0;
}

/// Return a typed pointer to an element, or `nil` when out of bounds.
export fn get⟨T⟩(vec: *Vec⟨T⟩, index: u32) -> ?*T {
    if index >= vec.len {
        return nil;
    }
    return &vec.data[index];
}

/// Append an element, returning `false` when the vector is full.
export fn push⟨T⟩(vec: *mut Vec⟨T⟩, value: T) -> bool {
    if vec.len >= vec.data.len {
        return false;
    }
    set vec.data[vec.len] = value;
    set vec.len += 1;
    return true;
}

/// Replace an initialized element, returning `false` when out of bounds.
export fn put⟨T⟩(vec: *mut Vec⟨T⟩, index: u32, value: T) -> bool {
    if index >= vec.len {
        return false;
    }
    set vec.data[index] = value;
    return true;
}

/// Remove and return the last element, or `nil` when empty.
export fn pop⟨T⟩(vec: *mut Vec⟨T⟩) -> ?T {
    if vec.len == 0 {
        return nil;
    }
    set vec.len -= 1;
    return vec.data[vec.len];
}
