Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/std/vec/index.nct

index.nct

//! Common owning variable-length array type.
//!
//! `[T]` is the compiler built-in unsized array data type. `&[T]` and `&+[T]`
//! are non-owning array slice types. Vec<T> is the owning variable-length array
//! type. Its storage details are intentionally not exposed outside `std/vec`.
//!
//! Vec owns the fully initialized prefix `[0, len)`. Push transfers values into
//! that prefix, while clear and drop destroy its elements in reverse order.

use /iter.{ExactSizeIterator, Iterator, MutableViewIter, ViewIter}
use /mem.TryAllocator
see ./construction.nct
see ./into_iter.nct
see ./mutation.nct
see ./storage.nct

/// A forward iterator that owns a Vec allocation and its remaining elements.
pub struct VecIntoIter<T>

instance VecIntoIter<T> {
    impl ExactSizeIterator
    impl Iterator { .Item = T }
}

/// An owning, growable sequence with an initialized prefix of elements.
pub struct Vec<T>

construct Vec<T> {
    /// Constructs a Vec from owned elements evaluated from left to right.
    pub literal [](...items: T): Self

    /// Constructs an empty Vec without binding storage.
    pub func empty(): Self

    /// Constructs an empty Vec with at least the requested element capacity.
    pub func with_capacity(requested_capacity: usize): Self

    /// Constructs an empty Vec using recoverable storage from `allocator`.
    pub func try_with_capacity(
        allocator: &+TryAllocator,
        requested_capacity: usize,
    ): Self!

    /// Copies every element of a borrowed slice into a new Vec.
    pub func from_slice(values: &[T]): Self where copy T

    /// Consumes an iterator and grows a Vec without an intermediate collection.
    pub func from_iter<I>(iterator: I): Self where I impl Iterator { .Item = T }

    /// Consumes an exact iterator after reserving its initial reported remainder.
    pub func from_exact_iter<I>(
        iterator: I,
    ): Self where I impl ExactSizeIterator { .Item = T }

    /// Copies a borrowed slice using recoverable storage from `allocator`.
    pub func try_from_slice(
        allocator: &+TryAllocator,
        values: &[T],
    ): Self! from allocator | values where copy T
}

instance Vec<T> {
    /// Exposes the initialized element prefix as a readonly view.
    pub noalloc coerce &self as &[T]

    /// Exposes the initialized element prefix as a readwrite view.
    pub noalloc coerce &+self as &+[T]

    /// Creates an allocation-free iterator over readonly element borrows.
    pub noalloc operator (...&self): ViewIter<T>

    /// Creates an allocation-free iterator over readwrite element borrows.
    pub noalloc operator (...&+self): MutableViewIter<T>

    /// Transfers the allocation and every element into an owning iterator.
    pub operator (...self): VecIntoIter<T>

    /// Returns the readonly iterator explicitly for method-chain construction.
    pub noalloc method &self.iter(): ViewIter<T>

    /// Returns the readwrite iterator explicitly for mutation algorithms.
    pub noalloc method &+self.iter_mut(): MutableViewIter<T>

    /// Returns the owning iterator explicitly for method-chain construction.
    pub method self.into_iter(): VecIntoIter<T>

    /// Returns how many elements fit without growth.
    pub noalloc method &self.capacity(): usize

    /// Ensures capacity for at least `additional` more elements.
    pub method &+self.reserve(additional: usize): void

    /// Ensures additional capacity with recoverable allocation failure.
    pub method &+self.try_reserve(additional: usize): void!

    /// Destroys every initialized element and keeps the allocation for reuse.
    pub method &+self.clear(): void

    /// Drops elements after `requested_len` and does nothing when already shorter.
    pub method &+self.truncate(requested_len: usize): void

    /// Keeps elements accepted by `predicate` while preserving their order.
    pub method &+self.retain<F>(predicate: F): void where F: &+func(&T): bool

    /// Transfers `value` into the end of the initialized prefix.
    pub method &+self.push(value: T): void

    /// Transfers `value` into the end with recoverable allocation failure.
    pub method &+self.try_push(value: T): void!

    /// Inserts an owned value and aborts if growth or bounds validation fails.
    pub method &+self.insert(index: usize, value: T): void

    /// Inserts an owned value with recoverable allocation and bounds failure.
    pub method &+self.try_insert(index: usize, value: T): void!

    /// Removes and transfers an element, or returns `none` out of bounds.
    pub method &+self.remove(index: usize): T?

    /// Removes an element without preserving order for package-internal dense storage.
    pub(/) method &+self.swap_remove(index: usize): T?

    /// Transfers and returns the last initialized element, or `none` when empty.
    pub method &+self.pop(): T?
}