Programming Language

Nocter

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

/development/std/iter/sources.nct

sources.nct

//! Zero- and one-element owning iterators.

use std/iter.{ExactSizeIterator, Iterator}
use std/ptr.{from_ref_mut, store_value_to_ptr, take_value_at_ptr}

/// An iterator that never yields an item.
pub struct EmptyIter<T> {
    exhausted: bool
}

/// Constructs an empty iterator.
pub func empty<T>(): EmptyIter<T> {
    return EmptyIter<T> { exhausted: true }
}

impl<T> ExactSizeIterator<T> for EmptyIter<T> {
    /// Returns zero because no item can be yielded.
    method &self.remaining_len(): usize {
        return 0
    }
}

impl<T> Iterator<T> for EmptyIter<T> {
    /// Returns `none` for every call.
    method &+self.next(): T? from self {
        return none
    }
}

/// An iterator that owns at most one unconsumed item.
pub struct OnceIter<T> {
    item: T?
    remaining: usize
}

/// Constructs an iterator that yields `item` once.
pub func once<T>(item: T): OnceIter<T> from item {
    return OnceIter<T> {
        item: move item,
        remaining: 1,
    }
}

impl<T> ExactSizeIterator<T> for OnceIter<T> {
    /// Returns one while the item remains and zero after it is yielded.
    method &self.remaining_len(): usize {
        return self.remaining
    }
}

impl<T> Iterator<T> for OnceIter<T> {
    /// Transfers the owned item once, then returns `none`.
    method &+self.next(): T? from self {
        if self.remaining == 0 {
            return none
        }
        let empty_value: T? = none
        let pointer = from_ref_mut(&+self.item)
        let previous: T? = take_value_at_ptr(pointer, 0)
        store_value_to_ptr(pointer, 0, move empty_value)
        self.remaining = 0
        let item = previous?
        return move item
    }
}