sain.collections.vec API documentation

# sain.collections.vec

A contiguous growable alternative to builtin `list` with extra functionalities.

###### Example

    names = Vec[str]()

    names.push('foo')
    names.push('bar')

    print(names) # ['foo', 'bar']
    assert names.len() == 2

View Source

       1# BSD 3-Clause License
       2#
       3# Copyright (c) 2022-Present, nxtlo
       4# All rights reserved.
       5#
       6# Redistribution and use in source and binary forms, with or without
       7# modification, are permitted provided that the following conditions are met:
       8#
       9# * Redistributions of source code must retain the above copyright notice, this
      10#   list of conditions and the following disclaimer.
      11#
      12# * Redistributions in binary form must reproduce the above copyright notice,
      13#   this list of conditions and the following disclaimer in the documentation
      14#   and/or other materials provided with the distribution.
      15#
      16# * Neither the name of the copyright holder nor the names of its
      17#   contributors may be used to endorse or promote products derived from
      18#   this software without specific prior written permission.
      19#
      20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      23# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
      24# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      25# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      26# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
      27# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
      28# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30"""A contiguous growable alternative to builtin `list` with extra functionalities.
      31
      32Example
      33-------
      34```py
      35names = Vec[str]()
      36
      37names.push('foo')
      38names.push('bar')
      39
      40print(names) # ['foo', 'bar']
      41assert names.len() == 2
      42```
      43"""
      44
      45from __future__ import annotations
      46
      47__all__ = ("Vec",)
      48
      49import sys as _sys
      50import typing
      51from collections import abc as collections
      52
      53from sain import iter as _iter
      54from sain import option as _option
      55from sain import result as _result
      56from sain.collections.slice import Slice
      57from sain.collections.slice import SliceMut
      58from sain.collections.slice import SpecContains
      59from sain.macros import rustc_diagnostic_item
      60
      61if typing.TYPE_CHECKING:
      62    from _typeshed import SupportsRichComparison
      63
      64    from sain import Result
      65
      66T = typing.TypeVar("T")
      67
      68
      69@rustc_diagnostic_item("Vec")
      70@typing.final
      71class Vec(typing.Generic[T], collections.MutableSequence[T], SpecContains[T]):
      72    """A contiguous growable alternative to builtin `list` with extra functionalities.
      73
      74    The layout of `Vec<T>` is exactly the same as `list<T>`.
      75    Which means `list<T>`'s methods are inherited into `Vec<T>`.
      76
      77    Example
      78    -------
      79    ```py
      80    names = Vec()
      81    names.push('foo')
      82    names.push('bar')
      83
      84    print(names) # ['foo', 'bar']
      85    assert names.len() == 2
      86    ```
      87
      88    Constructing
      89    ------------
      90    * `Vec()`: Create an empty vec, this will not allocate the initial buffer.
      91    * `Vec(other_list)`: Create a vec which points to `other_list`
      92    * `Vec([1, 2, 3])`: Create a vec with `[1, 2, 3]` pre-allocated.
      93    * `Vec(iterable)`: Create a vec from an `iterable`, This is `O(n)` where `n` is the number of elements,
      94    since it copies `iterable`'s elements into a new list.
      95    * `Vec.with_capacity(5)`: Create a vec that can hold up to 5 elements
      96
      97    Iterating over `Vec`
      98    -------------------
      99    There're two ways to iterate over a `Vec`. The first is to normally use `for` loop.
     100
     101    ```py
     102    for i in names:
     103        print(i)
     104
     105    # foo
     106    # bar
     107    ```
     108
     109    The second is to use `Vec.iter`, which yields all items in this `Vec` from start to end.
     110    Then the iterator gets exhausted as usual, See `sain.Iterator`.
     111
     112    ```py
     113    iterator = names.iter()
     114    for name in iterator.map(str.upper):
     115        print(name)
     116
     117    # FOO
     118    # BAR
     119
     120    # No more items, The actual vec is left unchanged.
     121    assert iterator.next().is_none()
     122    ```
     123
     124    ## Comparison operators
     125    A `Vec` may be compared with another `Vec` or a `list`, any other type will return `False`
     126
     127    ```py
     128    vec = Vec([1, 2, 3])
     129    assert vec == [1, 2, 3] # True
     130    assert vec != (1, 2, 3)
     131    ```
     132
     133    Zero-Copy
     134    ---------
     135    A vec that gets initialized from a `list` will *point* to it and doesn't copy it.
     136    So any element that gets appended to the list will also get pushed into the vec
     137    that's pointing to it and vice-versa.
     138
     139    ```py
     140    cells: list[str] = []
     141    vec = Vec(cells) # This DOES NOT copy the `cells`.
     142
     143    cells.append("foo")
     144    vec[0] == "foo"  # True
     145    ```
     146
     147    The opposite of the above is to initialize the vec from either
     148    an iterable or args, or copy the list.
     149
     150    ```py
     151    from sain.collections import vec, Vec
     152
     153    # Copy the list into a vec.
     154    vec = Vec(cells[:])
     155    cells.append("bar")
     156
     157    vec[1] # IndexError: "bar" doesn't exist in vec.
     158    ```
     159    """
     160
     161    __slots__ = ("_ptr", "_capacity")
     162
     163    @typing.overload
     164    def __init__(self) -> None: ...
     165
     166    @typing.overload
     167    def __init__(self, iterable: collections.Iterable[T]) -> None: ...
     168
     169    def __init__(self, iterable: collections.Iterable[T] | None = None) -> None:
     170        """Create an empty `Vec<T>`.
     171
     172        The vector will not allocate until elements are pushed onto it.
     173
     174        Example
     175        ------
     176        ```py
     177        vec: Vec[float] = Vec()
     178        ```
     179        """
     180        # We won't allocate to build the list here.
     181        # Instead, On first push or fist indexed set
     182        # we allocate if it was None.
     183        if isinstance(iterable, list):
     184            # Calling `list()` on another list will copy it, So instead we just point to it.
     185            self._ptr = iterable
     186        elif isinstance(iterable, Vec):
     187            self._ptr = iterable._ptr
     188        # any other iterable that ain't a list needs to get copied into a new list.
     189        else:
     190            self._ptr: list[T] | None = list(iterable) if iterable else None
     191
     192        self._capacity: int | None = None
     193
     194    @classmethod
     195    def with_capacity(cls, capacity: int) -> Vec[T]:
     196        """Create a new `Vec` with at least the specified capacity.
     197        This vec will be able to hold `capacity` elements without pushing further.
     198
     199        Check out `Vec.push_within_capacity` as well.
     200
     201        Example
     202        -------
     203        ```py
     204        vec = Vec.with_capacity(3)
     205        assert vec.len() == 0 and vec.capacity() >= 3
     206
     207        vec.push(1)
     208        vec.push(2)
     209        vec.push(3)
     210        print(vec.len()) # 3
     211
     212        # This won't push.
     213        vec.push(4)
     214        ```
     215        """
     216        v = cls()
     217        v._capacity = capacity
     218        return v
     219
     220    def as_ref(self) -> Slice[T]:
     221        """Return an immutable view over this vector elements.
     222
     223        No copying occurs.
     224
     225        Example
     226        -------
     227        ```py
     228        def send_bytes(v: Slice[int]) -> None:
     229            # access `vec` in a read-only mode.
     230            socket.write_all(v)
     231
     232        buf = Vec([1, 2, 3])
     233        send_bytes(buf.as_ref())
     234        ```
     235        """
     236        return Slice(self)
     237
     238    def as_mut(self) -> SliceMut[T]:
     239        """Return a mutable view over this vector elements.
     240
     241        No copying occurs.
     242
     243        Example
     244        -------
     245        ```py
     246        def read_bytes(buf: SliceMut[int]) -> None:
     247            socket.read_to_end(buf.as_mut())
     248
     249        buf: Vec[int] = Vec()
     250        read_bytes(buf.as_mut()) # or just `buf`
     251        assert vec.len() >= 1
     252        ```
     253        """
     254        return SliceMut(self)
     255
     256    def len(self) -> int:
     257        """Return the number of elements in this vector.
     258
     259        Example
     260        -------
     261        ```py
     262        vec = Vec((1,2,3))
     263
     264        assert vec.len() == 3
     265        ```
     266        """
     267        return self.__len__()
     268
     269    def capacity(self) -> int:
     270        """Return the capacity of this vector if set, 0 if not .
     271
     272        The number `0` here has two different Meanings:
     273        - The first means the `Vec` doesn't have a specific capacity set.
     274        - The second means the `Vec` literally initialized with `0` capacity.
     275
     276        Example
     277        -------
     278        ```py
     279        vec_with_cap = Vec.with_capacity(3)
     280        assert vec_with_cap.capacity().unwrap() == 3
     281
     282        vec = Vec([1, 2, 3])
     283        assert vec.capacity() == 0
     284        ```
     285        """
     286        return 0 if self._capacity is None else self._capacity
     287
     288    def iter(self) -> _iter.TrustedIter[T]:
     289        """Returns an iterator over this vector elements.
     290
     291        Example
     292        -------
     293        ```py
     294        vec = Vec([1 ,2, 3])
     295        for element in vec.iter().map(str):
     296            print(element)
     297        ```
     298        """
     299        return _iter.TrustedIter(self._ptr or ())
     300
     301    def is_empty(self) -> bool:
     302        """Returns true if the vector contains no elements.
     303
     304        Inlined into:
     305        ```py
     306        not self.vec
     307        ```
     308        """
     309        return not self._ptr
     310
     311    def leak(self) -> list[T]:
     312        """Consumes and leaks the Vec, returning a mutable reference to the contents.
     313
     314        After calling this, this vec will no longer reference the underlying buffer,
     315        therefore, it becomes unusable.
     316
     317        if `self` is uninitialized, an empty list is returned.
     318
     319        This function is only useful when you want to detach from a `Vec<T>` and get a `list[T]` without
     320        any copies.
     321
     322        Example
     323        -------
     324        ```py
     325        x = Vec([1, 2, 3])
     326        owned = x.leak()
     327        # x is now unusable.
     328        owned[0] += 1
     329        assert owned == [2, 2, 3]
     330        ```
     331        """
     332        if self._ptr is not None:
     333            # don't point to `_ptr` anymore.
     334            tmp = self._ptr
     335            del self._ptr
     336            return tmp
     337
     338        return []
     339
     340    def split_off(self, at: int) -> Vec[T]:
     341        """Split the vector off at the specified position, returning a new
     342        vec at the range of `[at : len]`, leaving `self` at `[at : vec_len]`.
     343
     344        if this vec is empty, `self` is returned unchanged.
     345
     346        Example
     347        -------
     348        ```py
     349        origin = Vec((1, 2, 3, 4))
     350        split = vec.split_off(2)
     351
     352        print(origin, split)  # [1, 2], [3, 4]
     353        ```
     354
     355        Raises
     356        ------
     357        `IndexError`
     358            This method will raise if `at` > `len(self)`
     359        """
     360        len_ = self.len()
     361        if at > len_:
     362            raise IndexError(
     363                f"Index `at` ({at}) should be <= than len of vector ({len_}) "
     364            ) from None
     365
     366        # Either the list is empty or uninit.
     367        if not self._ptr:
     368            return self
     369
     370        split = self[at:len_]  # split the items into a new vec.
     371        del self._ptr[at:len_]  # remove the items from the original list.
     372        return split
     373
     374    def split_first(self) -> _option.Option[tuple[T, collections.Sequence[T]]]:
     375        """Split the first and rest elements of the vector, If empty, `None` is returned.
     376
     377        Example
     378        -------
     379        ```py
     380        vec = Vec([1, 2, 3])
     381        split = vec.split_first()
     382        assert split == Some((1, [2, 3]))
     383
     384        vec: Vec[int] = Vec()
     385        split = vec.split_first()
     386        assert split.is_none()
     387        ```
     388        """
     389        if not self._ptr:
     390            return _option.NOTHING
     391
     392        # optimized to only one element in the vector.
     393        if self.len() == 1:
     394            return _option.Some((self[0], ()))
     395
     396        first, *rest = self._ptr
     397        return _option.Some((first, rest))
     398
     399    def split_last(self) -> _option.Option[tuple[T, collections.Sequence[T]]]:
     400        """Split the last and rest elements of the vector, If empty, `None` is returned.
     401
     402        Example
     403        -------
     404        ```py
     405        vec = Vec([1, 2, 3])
     406        last, rest = vec.split_last().unwrap()
     407        assert (last, rest) == [3, [1, 2]]
     408        ```
     409        """
     410        if not self._ptr:
     411            return _option.NOTHING
     412
     413        # optimized to only one element in the vector.
     414        if self.len() == 1:
     415            return _option.Some((self[0], ()))
     416
     417        last, *rest = self._ptr[-1], *self._ptr[:-1]
     418        return _option.Some((last, rest))
     419
     420    def split_at(self, mid: int) -> tuple[Vec[T], Vec[T]]:
     421        """Divide `self` into two at an index.
     422
     423        The first will contain all elements from `[0:mid]` excluding `mid` it self.
     424        and the second will contain the remaining elements.
     425
     426        if `mid` > `self.len()`, Then all elements will be moved to the left,
     427        returning an empty vec in right.
     428
     429        Example
     430        -------
     431        ```py
     432        buffer = Vec((1, 2, 3, 4))
     433        left, right = buffer.split_at(0)
     434        assert left == [] and right == [1, 2, 3, 4]
     435
     436        left, right = buffer.split_at(2)
     437        assert left == [1, 2] and right == [2, 3]
     438        ```
     439
     440        The is roughly the implementation
     441        ```py
     442        vec[0:mid], vec[mid:]
     443        ```
     444        """
     445        return self[0:mid], self[mid:]
     446
     447    def swap(self, a: int, b: int):
     448        """Swap two elements in the vec.
     449
     450        if `a` equals to `b` then it's guaranteed that elements won't change value.
     451
     452        Example
     453        -------
     454        ```py
     455        buf = Vec([1, 2, 3, 4])
     456        buf.swap(0, 3)
     457        assert buf == [4, 2, 3, 1]
     458        ```
     459
     460        Raises
     461        ------
     462        IndexError
     463            If the positions of `a` or `b` are out of index.
     464        """
     465        if self[a] == self[b]:
     466            return
     467
     468        self[a], self[b] = self[b], self[a]
     469
     470    def swap_unchecked(self, a: int, b: int):
     471        """Swap two elements in the vec. without checking if `a` == `b`.
     472
     473        If you care about `a` and `b` equality, see `Vec.swap`.
     474
     475        Example
     476        -------
     477        ```py
     478        buf = Vec([1, 2, 3, 1])
     479        buf.swap_unchecked(0, 3)
     480        assert buf == [1, 2, 3, 1]
     481        ```
     482
     483        Raises
     484        ------
     485        IndexError
     486            If the positions of `a` or `b` are out of index.
     487        """
     488        self[a], self[b] = self[b], self[a]
     489
     490    def first(self) -> _option.Option[T]:
     491        """Get the first element in this vec, returning `None` if there's none.
     492
     493        Example
     494        -------
     495        ```py
     496        vec = Vec((1,2,3))
     497        first = vec.first()
     498        assert ~first == 1
     499        ```
     500        """
     501        return self.get(0)
     502
     503    def last(self) -> _option.Option[T]:
     504        """Get the last element in this vec, returning `None` if there's none.
     505
     506        Example
     507        -------
     508        ```py
     509        vec = Vec([1, 2, 3, 4])
     510        first = vec.last()
     511        assert ~first == 4
     512        ```
     513        """
     514        return self.get(-1)
     515
     516    def truncate(self, size: int) -> None:
     517        """Shortens the vec, keeping the first `size` elements and dropping the rest.
     518
     519        Example
     520        -------
     521        ```py
     522        vec = Vec([1,2,3])
     523        vec.truncate(1)
     524        assert vec == [1]
     525        ```
     526        """
     527        if not self._ptr:
     528            return
     529
     530        del self._ptr[size:]
     531
     532    def retain(self, f: collections.Callable[[T], bool]) -> None:
     533        """Retains only the elements specified by the predicate.
     534
     535        This operation occurs in-place without copying the original list.
     536
     537        Example
     538        -------
     539        ```py
     540        vec = Vec([1, 2, 3])
     541        vec.retain(lambda elem: elem > 1)
     542
     543        assert vec == [2, 3]
     544        ```
     545
     546        The impl for this method is very simple
     547        ```py
     548        for idx, e in enumerate(vec):
     549            if not f(e):
     550                del vec[idx]
     551        ```
     552        """
     553        if not self._ptr:
     554            return
     555
     556        idx = 0
     557        while idx < len(self._ptr):
     558            if not f(self._ptr[idx]):
     559                del self._ptr[idx]
     560            else:
     561                idx += 1
     562
     563    def swap_remove(self, item: T) -> T:
     564        """Remove the first appearance of `item` from this vector and return it.
     565
     566        Raises
     567        ------
     568        * `ValueError`: if `item` is not in this vector.
     569        * `MemoryError`: if this vector hasn't allocated, Aka nothing has been pushed to it.
     570
     571        Example
     572        -------
     573        ```py
     574        vec = Vec(('a', 'b', 'c'))
     575        element = vec.remove('a')
     576        assert vec == ['b', 'c'] and element == 'a'
     577        ```
     578        """
     579        if self._ptr is None:
     580            raise MemoryError("Vec is unallocated.") from None
     581
     582        return self._ptr.pop(self.index(item))
     583
     584    def fill(self, value: T) -> None:
     585        """Fill `self` with the given `value`.
     586
     587        Nothing happens if the vec is empty or unallocated.
     588
     589        Example
     590        ```py
     591        a = Vec([0, 1, 2, 3])
     592        a.fill(0)
     593        assert a == [0, 0, 0, 0]
     594        ```
     595        """
     596        if not self._ptr:
     597            return
     598
     599        for n, _ in enumerate(self):
     600            self[n] = value
     601
     602    def push(self, item: T) -> None:
     603        """Push an element at the end of the vector.
     604
     605        Example
     606        -------
     607        ```py
     608        vec = Vec()
     609        vec.push(1)
     610
     611        assert vec == [1]
     612        ```
     613        """
     614        if self._capacity is not None:
     615            self.push_within_capacity(item)
     616            return
     617
     618        if self._ptr is None:
     619            self._ptr = []
     620
     621        self._ptr.append(item)
     622
     623    def push_within_capacity(self, x: T) -> Result[None, T]:
     624        """Appends an element if there is sufficient spare capacity, otherwise an error is returned with the element.
     625
     626        Example
     627        -------
     628        ```py
     629        vec: Vec[int] = Vec.with_capacity(3)
     630        for i in range(3):
     631            match vec.push_within_capacity(i):
     632                case Ok(_):
     633                    print("All good.")
     634                case Err(elem):
     635                    print("Reached max cap :< can't push", elem)
     636        ```
     637
     638        Or you can also just call `Vec.push` and it will push if there's is sufficient capacity.
     639        ```py
     640        vec: Vec[int] = Vec.with_capacity(3)
     641
     642        vec.extend((1, 2, 3))
     643        vec.push(4)
     644
     645        assert vec.len() == 3
     646        ```
     647        """
     648        if self._ptr is None:
     649            self._ptr = []
     650
     651        if self.len() == self._capacity:
     652            return _result.Err(x)
     653
     654        self._ptr.append(x)
     655        return _result.Ok(None)
     656
     657    def reserve(self, additional: int) -> None:
     658        """Reserves capacity for at least additional more elements to be inserted in the given Vec<T>.
     659
     660        Example
     661        -------
     662        ```py
     663        vec = Vec.with_capacity(3)
     664        is_vip = random.choice((True, False))
     665
     666        for i in range(4):
     667            match vec.push_within_capacity(i):
     668                case Ok(_):
     669                    print("All good")
     670                case Err(person):
     671                    # If the person is a VIP, then reserve for one more.
     672                    if is_vip:
     673                        vec.reserve(1)
     674                        continue
     675
     676                    # is_vip was false.
     677                    print("Can't reserve for non-VIP members...", person)
     678                    break
     679        ```
     680        """
     681        if self._capacity is not None:
     682            self._capacity += additional
     683
     684    def shrink_to_fit(self) -> None:
     685        """Shrink the capacity of this `Vec` to match its length.
     686
     687        If `self` is initialized with no capacity, This is a `NOP`.
     688
     689        Example
     690        -------
     691        ```py
     692        s = Vec([1, 2, 3, 4])
     693
     694        s.reserve(100)
     695        s.shrink_to_fit()
     696        assert s.capacity() == 4
     697        ```
     698        """
     699        if self._capacity is None:
     700            return
     701
     702        # The capacity is never less than the length.
     703        self._capacity = min(self.__len__(), self._capacity)
     704
     705    def shrink_to(self, min_capacity: int) -> None:
     706        """Shrink the capacity of this `Vec` to a minimum specified capacity.
     707
     708        If `self` is initialized with no capacity or the current capacity is less than the lower limit,
     709        This is a `NOP`.
     710
     711        Example
     712        -------
     713        ```py
     714        vec = Vec.with_capacity(10)
     715        vec.extend([1, 2, 3])
     716        assert vec.capacity() >= 10
     717        vec.shrink_to(4)
     718        assert vec.capacity() >= 4
     719        vec.shrink_to(0)
     720        ```
     721        """
     722        if self._capacity is None or self._capacity <= min_capacity:
     723            return
     724
     725        # Ensure the capacity is not reduced below the current length of the vector.
     726        self._capacity = max(self.__len__(), min_capacity)
     727
     728    ##########################
     729    # * Builtin Operations *
     730    ##########################
     731
     732    def append(self, value: T) -> None:
     733        """An alias to `Vec.push`."""
     734        self.push(value)
     735
     736    def get(self, index: int) -> _option.Option[T]:
     737        """Get the item at the given index, or `Some[None]` if its out of bounds.
     738
     739        Example
     740        -------
     741        ```py
     742        vec = Vec((1, 2, 3))
     743        vec.get(0) == Some(1)
     744        vec.get(3) == Some(None)
     745        ```
     746        """
     747        try:
     748            return _option.Some(self[index])
     749        except IndexError:
     750            return _option.NOTHING
     751
     752    def insert(self, index: int, value: T) -> None:
     753        """Insert an element at the position `index`.
     754
     755        Example
     756        --------
     757        ```py
     758        vec = Vec((2, 3))
     759        vec.insert(0, 1)
     760        assert vec == [1, 2, 3]
     761        ```
     762        """
     763        self.__setitem__(index, value)
     764
     765    def pop(self, index: int = -1) -> _option.Option[T]:
     766        """Removes the last element from a vector and returns it, or `None` if it is empty.
     767
     768        Example
     769        -------
     770        ```py
     771        vec = Vec((1, 2, 3))
     772        assert vec.pop() == Some(3)
     773        assert vec == [1, 2]
     774        ```
     775        """
     776        if not self._ptr:
     777            return _option.NOTHING
     778
     779        return _option.Some(self._ptr.pop(index))
     780
     781    def pop_if(self, pred: collections.Callable[[T], bool]) -> _option.Option[T]:
     782        """Removes the last element from a vector and returns it if `f` returns `True`,
     783        or `None` if it is empty.
     784
     785        Example
     786        -------
     787        ```py
     788        vec = Vec((1, 2, 3))
     789        assert vec.pop_if(lambda num: num * 2 == 6) == Some(3)
     790        assert vec == [1, 2]
     791        ```
     792        """
     793        if not self._ptr:
     794            return _option.NOTHING
     795
     796        if pred(self[-1]):
     797            return self.pop()
     798
     799        return _option.NOTHING
     800
     801    def dedup(self) -> None:
     802        """Removes consecutive repeated elements in the vector according to their `__eq__`
     803        implementation.
     804
     805        Example
     806        -------
     807        ```py
     808        vec = Vec([1, 2, 2, 3, 2])
     809        vec.dedup()
     810        assert vec == [1, 2, 3, 2]
     811        """
     812        self.dedup_by(lambda a, b: a == b)
     813
     814    def dedup_by(self, same_bucket: collections.Callable[[T, T], bool]) -> None:
     815        """Removes all but the first of consecutive elements in the vector satisfying a given equality.
     816
     817        Example
     818        -------
     819        ```py
     820        vec = Vec(["foo", "bar", "Bar", "baz", "bar"])
     821        vec.dedup_by(lambda a, b: a.lower() == b.lower())
     822        assert vec == ["foo", "bar", "baz", "bar"]
     823        ```
     824
     825        Only remove consecutive duplicates.
     826        ```py
     827        vec = Vec([1, 2, 2, 3, 4, 1])
     828        vec.dedup_by(lambda a, b: a == b)
     829        # The final 1 is not adjacent to the first 1, so it is not removed.
     830        assert vec == [1, 2, 3, 4, 1]
     831        ```
     832        """
     833
     834        if not self._ptr or (len_ := len(self._ptr)) <= 1:
     835            return
     836
     837        idx = 1
     838        while idx < len_:
     839            if same_bucket(self._ptr[idx], self._ptr[idx - 1]):
     840                del self._ptr[idx]
     841                len_ -= 1
     842            else:
     843                idx += 1
     844
     845    def remove(self, item: T) -> None:
     846        """Remove the first appearance of `item` from this vector.
     847
     848        Example
     849        -------
     850        ```py
     851        vec = Vec(('a', 'b', 'c'))
     852        vec.remove('a')
     853        assert vec == ['b', 'c']
     854        ```
     855        """
     856        if not self._ptr:
     857            return
     858
     859        self._ptr.remove(item)
     860
     861    def extend(self, iterable: collections.Iterable[T]) -> None:
     862        """Extend this vector from another iterable.
     863
     864        Example
     865        -------
     866        ```py
     867        vec = Vec((1, 2, 3))
     868        vec.extend((4, 5, 6))
     869
     870        assert vec == [1, 2, 3, 4, 5, 6]
     871        ```
     872        """
     873        if self._ptr is None:
     874            self._ptr = []
     875
     876        self._ptr.extend(iterable)
     877
     878    def copy(self) -> Vec[T]:
     879        """Copy all elements of `self` into a new vector.
     880
     881        Example
     882        -------
     883        ```py
     884        original = Vec((1,2,3))
     885        copy = original.copy()
     886        copy.push(4)
     887
     888        print(original) # [1, 2, 3]
     889        ```
     890        """
     891        return Vec(self._ptr[:]) if self._ptr else Vec()
     892
     893    def clear(self) -> None:
     894        """Clear all elements of this vector.
     895
     896        Example
     897        -------
     898        ```py
     899        vec = Vec((1,2,3))
     900        vec.clear()
     901        assert vec.len() == 0
     902        ```
     903        """
     904        if not self._ptr:
     905            return
     906
     907        self._ptr.clear()
     908
     909    def sort(
     910        self,
     911        *,
     912        key: collections.Callable[[T], SupportsRichComparison] | None = None,
     913        reverse: bool = False,
     914    ) -> None:
     915        """This method sorts the list in place, using only < comparisons between items.
     916
     917        Example
     918        -------
     919        ```py
     920        vec = Vec((2, 1, 3))
     921        vec.sort()
     922        assert vec == [1, 2, 3]
     923        ```
     924        """
     925        if not self._ptr:
     926            return
     927
     928        # key can be `None` here just fine, idk why pyright is complaining.
     929        self._ptr.sort(key=key, reverse=reverse)  # pyright: ignore
     930
     931    def index(
     932        self, item: T, start: typing.SupportsIndex = 0, end: int = _sys.maxsize
     933    ) -> int:
     934        # << Official documentation >>
     935        """Return zero-based index in the vec of the first item whose value is equal to `item`.
     936        Raises a ValueError if there is no such item.
     937
     938        Example
     939        -------
     940        ```py
     941        vec = Vec((1, 2, 3))
     942        assert vec.index(2) == 1
     943        ```
     944        """
     945        if self._ptr is None:
     946            raise ValueError from None
     947
     948        return self._ptr.index(item, start, end)
     949
     950    def count(self, item: T) -> int:
     951        """Return the number of occurrences of `item` in the vec.
     952
     953        `0` is returned if the vector is empty or hasn't been initialized, as well if them item not found.
     954
     955        Example
     956        --------
     957        ```py
     958        vec = Vec((1, 2, 3, 3))
     959        assert vec.count(3) == 2
     960        ```
     961        """
     962        if self._ptr is None:
     963            return 0
     964
     965        return self._ptr.count(item)
     966
     967    def __len__(self) -> int:
     968        return len(self._ptr) if self._ptr else 0
     969
     970    def __setitem__(self, index: int, value: T):
     971        if not self._ptr:
     972            raise IndexError from None
     973
     974        self._ptr[index] = value
     975
     976    @typing.overload
     977    def __getitem__(self, index: slice) -> Vec[T]: ...
     978
     979    @typing.overload
     980    def __getitem__(self, index: int) -> T: ...
     981
     982    def __getitem__(self, index: int | slice) -> T | Vec[T]:
     983        if not self._ptr:
     984            raise IndexError("Index out of range")
     985
     986        if isinstance(index, slice):
     987            return Vec(self._ptr[index])
     988
     989        return self._ptr[index]
     990
     991    def __delitem__(self, index: int) -> None:
     992        if not self._ptr:
     993            return
     994
     995        del self._ptr[index]
     996
     997    def __contains__(self, element: T) -> bool:
     998        return element in self._ptr if self._ptr else False
     999
    1000    def __iter__(self) -> collections.Iterator[T]:
    1001        if self._ptr is None:
    1002            return iter(())
    1003
    1004        return self._ptr.__iter__()
    1005
    1006    def __repr__(self) -> str:
    1007        return "[]" if not self._ptr else repr(self._ptr)
    1008
    1009    def __eq__(self, other: Vec[T] | list[T]) -> bool:
    1010        if isinstance(other, Vec):
    1011            return self._ptr == other._ptr
    1012
    1013        return self._ptr == other
    1014
    1015    def __ne__(self, other: Vec[T] | list[T]) -> bool:
    1016        return not self.__eq__(other)
    1017
    1018    def __le__(self, other: list[T]) -> bool:
    1019        if not self._ptr:
    1020            return False
    1021
    1022        return self._ptr <= other
    1023
    1024    def __ge__(self, other: list[T]) -> bool:
    1025        if not self._ptr:
    1026            return False
    1027
    1028        return self._ptr >= other
    1029
    1030    def __lt__(self, other: list[T]) -> bool:
    1031        if not self._ptr:
    1032            return False
    1033
    1034        return self._ptr < other
    1035
    1036    def __gt__(self, other: list[T]) -> bool:
    1037        if not self._ptr:
    1038            return False
    1039
    1040        return self._ptr > other
    1041
    1042    def __bool__(self) -> bool:
    1043        return bool(self._ptr)
    1044
    1045    def __reversed__(self) -> collections.Iterator[T]:
    1046        return reversed(self._ptr or ())

@rustc_diagnostic_item('Vec')
@typing.final
class Vec(typing.Generic[~T], collections.abc.MutableSequence[~T], sain.collections.slice.SpecContains[~T]): View Source

      70@rustc_diagnostic_item("Vec")
      71@typing.final
      72class Vec(typing.Generic[T], collections.MutableSequence[T], SpecContains[T]):
      73    """A contiguous growable alternative to builtin `list` with extra functionalities.
      74
      75    The layout of `Vec<T>` is exactly the same as `list<T>`.
      76    Which means `list<T>`'s methods are inherited into `Vec<T>`.
      77
      78    Example
      79    -------
      80    ```py
      81    names = Vec()
      82    names.push('foo')
      83    names.push('bar')
      84
      85    print(names) # ['foo', 'bar']
      86    assert names.len() == 2
      87    ```
      88
      89    Constructing
      90    ------------
      91    * `Vec()`: Create an empty vec, this will not allocate the initial buffer.
      92    * `Vec(other_list)`: Create a vec which points to `other_list`
      93    * `Vec([1, 2, 3])`: Create a vec with `[1, 2, 3]` pre-allocated.
      94    * `Vec(iterable)`: Create a vec from an `iterable`, This is `O(n)` where `n` is the number of elements,
      95    since it copies `iterable`'s elements into a new list.
      96    * `Vec.with_capacity(5)`: Create a vec that can hold up to 5 elements
      97
      98    Iterating over `Vec`
      99    -------------------
     100    There're two ways to iterate over a `Vec`. The first is to normally use `for` loop.
     101
     102    ```py
     103    for i in names:
     104        print(i)
     105
     106    # foo
     107    # bar
     108    ```
     109
     110    The second is to use `Vec.iter`, which yields all items in this `Vec` from start to end.
     111    Then the iterator gets exhausted as usual, See `sain.Iterator`.
     112
     113    ```py
     114    iterator = names.iter()
     115    for name in iterator.map(str.upper):
     116        print(name)
     117
     118    # FOO
     119    # BAR
     120
     121    # No more items, The actual vec is left unchanged.
     122    assert iterator.next().is_none()
     123    ```
     124
     125    ## Comparison operators
     126    A `Vec` may be compared with another `Vec` or a `list`, any other type will return `False`
     127
     128    ```py
     129    vec = Vec([1, 2, 3])
     130    assert vec == [1, 2, 3] # True
     131    assert vec != (1, 2, 3)
     132    ```
     133
     134    Zero-Copy
     135    ---------
     136    A vec that gets initialized from a `list` will *point* to it and doesn't copy it.
     137    So any element that gets appended to the list will also get pushed into the vec
     138    that's pointing to it and vice-versa.
     139
     140    ```py
     141    cells: list[str] = []
     142    vec = Vec(cells) # This DOES NOT copy the `cells`.
     143
     144    cells.append("foo")
     145    vec[0] == "foo"  # True
     146    ```
     147
     148    The opposite of the above is to initialize the vec from either
     149    an iterable or args, or copy the list.
     150
     151    ```py
     152    from sain.collections import vec, Vec
     153
     154    # Copy the list into a vec.
     155    vec = Vec(cells[:])
     156    cells.append("bar")
     157
     158    vec[1] # IndexError: "bar" doesn't exist in vec.
     159    ```
     160    """
     161
     162    __slots__ = ("_ptr", "_capacity")
     163
     164    @typing.overload
     165    def __init__(self) -> None: ...
     166
     167    @typing.overload
     168    def __init__(self, iterable: collections.Iterable[T]) -> None: ...
     169
     170    def __init__(self, iterable: collections.Iterable[T] | None = None) -> None:
     171        """Create an empty `Vec<T>`.
     172
     173        The vector will not allocate until elements are pushed onto it.
     174
     175        Example
     176        ------
     177        ```py
     178        vec: Vec[float] = Vec()
     179        ```
     180        """
     181        # We won't allocate to build the list here.
     182        # Instead, On first push or fist indexed set
     183        # we allocate if it was None.
     184        if isinstance(iterable, list):
     185            # Calling `list()` on another list will copy it, So instead we just point to it.
     186            self._ptr = iterable
     187        elif isinstance(iterable, Vec):
     188            self._ptr = iterable._ptr
     189        # any other iterable that ain't a list needs to get copied into a new list.
     190        else:
     191            self._ptr: list[T] | None = list(iterable) if iterable else None
     192
     193        self._capacity: int | None = None
     194
     195    @classmethod
     196    def with_capacity(cls, capacity: int) -> Vec[T]:
     197        """Create a new `Vec` with at least the specified capacity.
     198        This vec will be able to hold `capacity` elements without pushing further.
     199
     200        Check out `Vec.push_within_capacity` as well.
     201
     202        Example
     203        -------
     204        ```py
     205        vec = Vec.with_capacity(3)
     206        assert vec.len() == 0 and vec.capacity() >= 3
     207
     208        vec.push(1)
     209        vec.push(2)
     210        vec.push(3)
     211        print(vec.len()) # 3
     212
     213        # This won't push.
     214        vec.push(4)
     215        ```
     216        """
     217        v = cls()
     218        v._capacity = capacity
     219        return v
     220
     221    def as_ref(self) -> Slice[T]:
     222        """Return an immutable view over this vector elements.
     223
     224        No copying occurs.
     225
     226        Example
     227        -------
     228        ```py
     229        def send_bytes(v: Slice[int]) -> None:
     230            # access `vec` in a read-only mode.
     231            socket.write_all(v)
     232
     233        buf = Vec([1, 2, 3])
     234        send_bytes(buf.as_ref())
     235        ```
     236        """
     237        return Slice(self)
     238
     239    def as_mut(self) -> SliceMut[T]:
     240        """Return a mutable view over this vector elements.
     241
     242        No copying occurs.
     243
     244        Example
     245        -------
     246        ```py
     247        def read_bytes(buf: SliceMut[int]) -> None:
     248            socket.read_to_end(buf.as_mut())
     249
     250        buf: Vec[int] = Vec()
     251        read_bytes(buf.as_mut()) # or just `buf`
     252        assert vec.len() >= 1
     253        ```
     254        """
     255        return SliceMut(self)
     256
     257    def len(self) -> int:
     258        """Return the number of elements in this vector.
     259
     260        Example
     261        -------
     262        ```py
     263        vec = Vec((1,2,3))
     264
     265        assert vec.len() == 3
     266        ```
     267        """
     268        return self.__len__()
     269
     270    def capacity(self) -> int:
     271        """Return the capacity of this vector if set, 0 if not .
     272
     273        The number `0` here has two different Meanings:
     274        - The first means the `Vec` doesn't have a specific capacity set.
     275        - The second means the `Vec` literally initialized with `0` capacity.
     276
     277        Example
     278        -------
     279        ```py
     280        vec_with_cap = Vec.with_capacity(3)
     281        assert vec_with_cap.capacity().unwrap() == 3
     282
     283        vec = Vec([1, 2, 3])
     284        assert vec.capacity() == 0
     285        ```
     286        """
     287        return 0 if self._capacity is None else self._capacity
     288
     289    def iter(self) -> _iter.TrustedIter[T]:
     290        """Returns an iterator over this vector elements.
     291
     292        Example
     293        -------
     294        ```py
     295        vec = Vec([1 ,2, 3])
     296        for element in vec.iter().map(str):
     297            print(element)
     298        ```
     299        """
     300        return _iter.TrustedIter(self._ptr or ())
     301
     302    def is_empty(self) -> bool:
     303        """Returns true if the vector contains no elements.
     304
     305        Inlined into:
     306        ```py
     307        not self.vec
     308        ```
     309        """
     310        return not self._ptr
     311
     312    def leak(self) -> list[T]:
     313        """Consumes and leaks the Vec, returning a mutable reference to the contents.
     314
     315        After calling this, this vec will no longer reference the underlying buffer,
     316        therefore, it becomes unusable.
     317
     318        if `self` is uninitialized, an empty list is returned.
     319
     320        This function is only useful when you want to detach from a `Vec<T>` and get a `list[T]` without
     321        any copies.
     322
     323        Example
     324        -------
     325        ```py
     326        x = Vec([1, 2, 3])
     327        owned = x.leak()
     328        # x is now unusable.
     329        owned[0] += 1
     330        assert owned == [2, 2, 3]
     331        ```
     332        """
     333        if self._ptr is not None:
     334            # don't point to `_ptr` anymore.
     335            tmp = self._ptr
     336            del self._ptr
     337            return tmp
     338
     339        return []
     340
     341    def split_off(self, at: int) -> Vec[T]:
     342        """Split the vector off at the specified position, returning a new
     343        vec at the range of `[at : len]`, leaving `self` at `[at : vec_len]`.
     344
     345        if this vec is empty, `self` is returned unchanged.
     346
     347        Example
     348        -------
     349        ```py
     350        origin = Vec((1, 2, 3, 4))
     351        split = vec.split_off(2)
     352
     353        print(origin, split)  # [1, 2], [3, 4]
     354        ```
     355
     356        Raises
     357        ------
     358        `IndexError`
     359            This method will raise if `at` > `len(self)`
     360        """
     361        len_ = self.len()
     362        if at > len_:
     363            raise IndexError(
     364                f"Index `at` ({at}) should be <= than len of vector ({len_}) "
     365            ) from None
     366
     367        # Either the list is empty or uninit.
     368        if not self._ptr:
     369            return self
     370
     371        split = self[at:len_]  # split the items into a new vec.
     372        del self._ptr[at:len_]  # remove the items from the original list.
     373        return split
     374
     375    def split_first(self) -> _option.Option[tuple[T, collections.Sequence[T]]]:
     376        """Split the first and rest elements of the vector, If empty, `None` is returned.
     377
     378        Example
     379        -------
     380        ```py
     381        vec = Vec([1, 2, 3])
     382        split = vec.split_first()
     383        assert split == Some((1, [2, 3]))
     384
     385        vec: Vec[int] = Vec()
     386        split = vec.split_first()
     387        assert split.is_none()
     388        ```
     389        """
     390        if not self._ptr:
     391            return _option.NOTHING
     392
     393        # optimized to only one element in the vector.
     394        if self.len() == 1:
     395            return _option.Some((self[0], ()))
     396
     397        first, *rest = self._ptr
     398        return _option.Some((first, rest))
     399
     400    def split_last(self) -> _option.Option[tuple[T, collections.Sequence[T]]]:
     401        """Split the last and rest elements of the vector, If empty, `None` is returned.
     402
     403        Example
     404        -------
     405        ```py
     406        vec = Vec([1, 2, 3])
     407        last, rest = vec.split_last().unwrap()
     408        assert (last, rest) == [3, [1, 2]]
     409        ```
     410        """
     411        if not self._ptr:
     412            return _option.NOTHING
     413
     414        # optimized to only one element in the vector.
     415        if self.len() == 1:
     416            return _option.Some((self[0], ()))
     417
     418        last, *rest = self._ptr[-1], *self._ptr[:-1]
     419        return _option.Some((last, rest))
     420
     421    def split_at(self, mid: int) -> tuple[Vec[T], Vec[T]]:
     422        """Divide `self` into two at an index.
     423
     424        The first will contain all elements from `[0:mid]` excluding `mid` it self.
     425        and the second will contain the remaining elements.
     426
     427        if `mid` > `self.len()`, Then all elements will be moved to the left,
     428        returning an empty vec in right.
     429
     430        Example
     431        -------
     432        ```py
     433        buffer = Vec((1, 2, 3, 4))
     434        left, right = buffer.split_at(0)
     435        assert left == [] and right == [1, 2, 3, 4]
     436
     437        left, right = buffer.split_at(2)
     438        assert left == [1, 2] and right == [2, 3]
     439        ```
     440
     441        The is roughly the implementation
     442        ```py
     443        vec[0:mid], vec[mid:]
     444        ```
     445        """
     446        return self[0:mid], self[mid:]
     447
     448    def swap(self, a: int, b: int):
     449        """Swap two elements in the vec.
     450
     451        if `a` equals to `b` then it's guaranteed that elements won't change value.
     452
     453        Example
     454        -------
     455        ```py
     456        buf = Vec([1, 2, 3, 4])
     457        buf.swap(0, 3)
     458        assert buf == [4, 2, 3, 1]
     459        ```
     460
     461        Raises
     462        ------
     463        IndexError
     464            If the positions of `a` or `b` are out of index.
     465        """
     466        if self[a] == self[b]:
     467            return
     468
     469        self[a], self[b] = self[b], self[a]
     470
     471    def swap_unchecked(self, a: int, b: int):
     472        """Swap two elements in the vec. without checking if `a` == `b`.
     473
     474        If you care about `a` and `b` equality, see `Vec.swap`.
     475
     476        Example
     477        -------
     478        ```py
     479        buf = Vec([1, 2, 3, 1])
     480        buf.swap_unchecked(0, 3)
     481        assert buf == [1, 2, 3, 1]
     482        ```
     483
     484        Raises
     485        ------
     486        IndexError
     487            If the positions of `a` or `b` are out of index.
     488        """
     489        self[a], self[b] = self[b], self[a]
     490
     491    def first(self) -> _option.Option[T]:
     492        """Get the first element in this vec, returning `None` if there's none.
     493
     494        Example
     495        -------
     496        ```py
     497        vec = Vec((1,2,3))
     498        first = vec.first()
     499        assert ~first == 1
     500        ```
     501        """
     502        return self.get(0)
     503
     504    def last(self) -> _option.Option[T]:
     505        """Get the last element in this vec, returning `None` if there's none.
     506
     507        Example
     508        -------
     509        ```py
     510        vec = Vec([1, 2, 3, 4])
     511        first = vec.last()
     512        assert ~first == 4
     513        ```
     514        """
     515        return self.get(-1)
     516
     517    def truncate(self, size: int) -> None:
     518        """Shortens the vec, keeping the first `size` elements and dropping the rest.
     519
     520        Example
     521        -------
     522        ```py
     523        vec = Vec([1,2,3])
     524        vec.truncate(1)
     525        assert vec == [1]
     526        ```
     527        """
     528        if not self._ptr:
     529            return
     530
     531        del self._ptr[size:]
     532
     533    def retain(self, f: collections.Callable[[T], bool]) -> None:
     534        """Retains only the elements specified by the predicate.
     535
     536        This operation occurs in-place without copying the original list.
     537
     538        Example
     539        -------
     540        ```py
     541        vec = Vec([1, 2, 3])
     542        vec.retain(lambda elem: elem > 1)
     543
     544        assert vec == [2, 3]
     545        ```
     546
     547        The impl for this method is very simple
     548        ```py
     549        for idx, e in enumerate(vec):
     550            if not f(e):
     551                del vec[idx]
     552        ```
     553        """
     554        if not self._ptr:
     555            return
     556
     557        idx = 0
     558        while idx < len(self._ptr):
     559            if not f(self._ptr[idx]):
     560                del self._ptr[idx]
     561            else:
     562                idx += 1
     563
     564    def swap_remove(self, item: T) -> T:
     565        """Remove the first appearance of `item` from this vector and return it.
     566
     567        Raises
     568        ------
     569        * `ValueError`: if `item` is not in this vector.
     570        * `MemoryError`: if this vector hasn't allocated, Aka nothing has been pushed to it.
     571
     572        Example
     573        -------
     574        ```py
     575        vec = Vec(('a', 'b', 'c'))
     576        element = vec.remove('a')
     577        assert vec == ['b', 'c'] and element == 'a'
     578        ```
     579        """
     580        if self._ptr is None:
     581            raise MemoryError("Vec is unallocated.") from None
     582
     583        return self._ptr.pop(self.index(item))
     584
     585    def fill(self, value: T) -> None:
     586        """Fill `self` with the given `value`.
     587
     588        Nothing happens if the vec is empty or unallocated.
     589
     590        Example
     591        ```py
     592        a = Vec([0, 1, 2, 3])
     593        a.fill(0)
     594        assert a == [0, 0, 0, 0]
     595        ```
     596        """
     597        if not self._ptr:
     598            return
     599
     600        for n, _ in enumerate(self):
     601            self[n] = value
     602
     603    def push(self, item: T) -> None:
     604        """Push an element at the end of the vector.
     605
     606        Example
     607        -------
     608        ```py
     609        vec = Vec()
     610        vec.push(1)
     611
     612        assert vec == [1]
     613        ```
     614        """
     615        if self._capacity is not None:
     616            self.push_within_capacity(item)
     617            return
     618
     619        if self._ptr is None:
     620            self._ptr = []
     621
     622        self._ptr.append(item)
     623
     624    def push_within_capacity(self, x: T) -> Result[None, T]:
     625        """Appends an element if there is sufficient spare capacity, otherwise an error is returned with the element.
     626
     627        Example
     628        -------
     629        ```py
     630        vec: Vec[int] = Vec.with_capacity(3)
     631        for i in range(3):
     632            match vec.push_within_capacity(i):
     633                case Ok(_):
     634                    print("All good.")
     635                case Err(elem):
     636                    print("Reached max cap :< can't push", elem)
     637        ```
     638
     639        Or you can also just call `Vec.push` and it will push if there's is sufficient capacity.
     640        ```py
     641        vec: Vec[int] = Vec.with_capacity(3)
     642
     643        vec.extend((1, 2, 3))
     644        vec.push(4)
     645
     646        assert vec.len() == 3
     647        ```
     648        """
     649        if self._ptr is None:
     650            self._ptr = []
     651
     652        if self.len() == self._capacity:
     653            return _result.Err(x)
     654
     655        self._ptr.append(x)
     656        return _result.Ok(None)
     657
     658    def reserve(self, additional: int) -> None:
     659        """Reserves capacity for at least additional more elements to be inserted in the given Vec<T>.
     660
     661        Example
     662        -------
     663        ```py
     664        vec = Vec.with_capacity(3)
     665        is_vip = random.choice((True, False))
     666
     667        for i in range(4):
     668            match vec.push_within_capacity(i):
     669                case Ok(_):
     670                    print("All good")
     671                case Err(person):
     672                    # If the person is a VIP, then reserve for one more.
     673                    if is_vip:
     674                        vec.reserve(1)
     675                        continue
     676
     677                    # is_vip was false.
     678                    print("Can't reserve for non-VIP members...", person)
     679                    break
     680        ```
     681        """
     682        if self._capacity is not None:
     683            self._capacity += additional
     684
     685    def shrink_to_fit(self) -> None:
     686        """Shrink the capacity of this `Vec` to match its length.
     687
     688        If `self` is initialized with no capacity, This is a `NOP`.
     689
     690        Example
     691        -------
     692        ```py
     693        s = Vec([1, 2, 3, 4])
     694
     695        s.reserve(100)
     696        s.shrink_to_fit()
     697        assert s.capacity() == 4
     698        ```
     699        """
     700        if self._capacity is None:
     701            return
     702
     703        # The capacity is never less than the length.
     704        self._capacity = min(self.__len__(), self._capacity)
     705
     706    def shrink_to(self, min_capacity: int) -> None:
     707        """Shrink the capacity of this `Vec` to a minimum specified capacity.
     708
     709        If `self` is initialized with no capacity or the current capacity is less than the lower limit,
     710        This is a `NOP`.
     711
     712        Example
     713        -------
     714        ```py
     715        vec = Vec.with_capacity(10)
     716        vec.extend([1, 2, 3])
     717        assert vec.capacity() >= 10
     718        vec.shrink_to(4)
     719        assert vec.capacity() >= 4
     720        vec.shrink_to(0)
     721        ```
     722        """
     723        if self._capacity is None or self._capacity <= min_capacity:
     724            return
     725
     726        # Ensure the capacity is not reduced below the current length of the vector.
     727        self._capacity = max(self.__len__(), min_capacity)
     728
     729    ##########################
     730    # * Builtin Operations *
     731    ##########################
     732
     733    def append(self, value: T) -> None:
     734        """An alias to `Vec.push`."""
     735        self.push(value)
     736
     737    def get(self, index: int) -> _option.Option[T]:
     738        """Get the item at the given index, or `Some[None]` if its out of bounds.
     739
     740        Example
     741        -------
     742        ```py
     743        vec = Vec((1, 2, 3))
     744        vec.get(0) == Some(1)
     745        vec.get(3) == Some(None)
     746        ```
     747        """
     748        try:
     749            return _option.Some(self[index])
     750        except IndexError:
     751            return _option.NOTHING
     752
     753    def insert(self, index: int, value: T) -> None:
     754        """Insert an element at the position `index`.
     755
     756        Example
     757        --------
     758        ```py
     759        vec = Vec((2, 3))
     760        vec.insert(0, 1)
     761        assert vec == [1, 2, 3]
     762        ```
     763        """
     764        self.__setitem__(index, value)
     765
     766    def pop(self, index: int = -1) -> _option.Option[T]:
     767        """Removes the last element from a vector and returns it, or `None` if it is empty.
     768
     769        Example
     770        -------
     771        ```py
     772        vec = Vec((1, 2, 3))
     773        assert vec.pop() == Some(3)
     774        assert vec == [1, 2]
     775        ```
     776        """
     777        if not self._ptr:
     778            return _option.NOTHING
     779
     780        return _option.Some(self._ptr.pop(index))
     781
     782    def pop_if(self, pred: collections.Callable[[T], bool]) -> _option.Option[T]:
     783        """Removes the last element from a vector and returns it if `f` returns `True`,
     784        or `None` if it is empty.
     785
     786        Example
     787        -------
     788        ```py
     789        vec = Vec((1, 2, 3))
     790        assert vec.pop_if(lambda num: num * 2 == 6) == Some(3)
     791        assert vec == [1, 2]
     792        ```
     793        """
     794        if not self._ptr:
     795            return _option.NOTHING
     796
     797        if pred(self[-1]):
     798            return self.pop()
     799
     800        return _option.NOTHING
     801
     802    def dedup(self) -> None:
     803        """Removes consecutive repeated elements in the vector according to their `__eq__`
     804        implementation.
     805
     806        Example
     807        -------
     808        ```py
     809        vec = Vec([1, 2, 2, 3, 2])
     810        vec.dedup()
     811        assert vec == [1, 2, 3, 2]
     812        """
     813        self.dedup_by(lambda a, b: a == b)
     814
     815    def dedup_by(self, same_bucket: collections.Callable[[T, T], bool]) -> None:
     816        """Removes all but the first of consecutive elements in the vector satisfying a given equality.
     817
     818        Example
     819        -------
     820        ```py
     821        vec = Vec(["foo", "bar", "Bar", "baz", "bar"])
     822        vec.dedup_by(lambda a, b: a.lower() == b.lower())
     823        assert vec == ["foo", "bar", "baz", "bar"]
     824        ```
     825
     826        Only remove consecutive duplicates.
     827        ```py
     828        vec = Vec([1, 2, 2, 3, 4, 1])
     829        vec.dedup_by(lambda a, b: a == b)
     830        # The final 1 is not adjacent to the first 1, so it is not removed.
     831        assert vec == [1, 2, 3, 4, 1]
     832        ```
     833        """
     834
     835        if not self._ptr or (len_ := len(self._ptr)) <= 1:
     836            return
     837
     838        idx = 1
     839        while idx < len_:
     840            if same_bucket(self._ptr[idx], self._ptr[idx - 1]):
     841                del self._ptr[idx]
     842                len_ -= 1
     843            else:
     844                idx += 1
     845
     846    def remove(self, item: T) -> None:
     847        """Remove the first appearance of `item` from this vector.
     848
     849        Example
     850        -------
     851        ```py
     852        vec = Vec(('a', 'b', 'c'))
     853        vec.remove('a')
     854        assert vec == ['b', 'c']
     855        ```
     856        """
     857        if not self._ptr:
     858            return
     859
     860        self._ptr.remove(item)
     861
     862    def extend(self, iterable: collections.Iterable[T]) -> None:
     863        """Extend this vector from another iterable.
     864
     865        Example
     866        -------
     867        ```py
     868        vec = Vec((1, 2, 3))
     869        vec.extend((4, 5, 6))
     870
     871        assert vec == [1, 2, 3, 4, 5, 6]
     872        ```
     873        """
     874        if self._ptr is None:
     875            self._ptr = []
     876
     877        self._ptr.extend(iterable)
     878
     879    def copy(self) -> Vec[T]:
     880        """Copy all elements of `self` into a new vector.
     881
     882        Example
     883        -------
     884        ```py
     885        original = Vec((1,2,3))
     886        copy = original.copy()
     887        copy.push(4)
     888
     889        print(original) # [1, 2, 3]
     890        ```
     891        """
     892        return Vec(self._ptr[:]) if self._ptr else Vec()
     893
     894    def clear(self) -> None:
     895        """Clear all elements of this vector.
     896
     897        Example
     898        -------
     899        ```py
     900        vec = Vec((1,2,3))
     901        vec.clear()
     902        assert vec.len() == 0
     903        ```
     904        """
     905        if not self._ptr:
     906            return
     907
     908        self._ptr.clear()
     909
     910    def sort(
     911        self,
     912        *,
     913        key: collections.Callable[[T], SupportsRichComparison] | None = None,
     914        reverse: bool = False,
     915    ) -> None:
     916        """This method sorts the list in place, using only < comparisons between items.
     917
     918        Example
     919        -------
     920        ```py
     921        vec = Vec((2, 1, 3))
     922        vec.sort()
     923        assert vec == [1, 2, 3]
     924        ```
     925        """
     926        if not self._ptr:
     927            return
     928
     929        # key can be `None` here just fine, idk why pyright is complaining.
     930        self._ptr.sort(key=key, reverse=reverse)  # pyright: ignore
     931
     932    def index(
     933        self, item: T, start: typing.SupportsIndex = 0, end: int = _sys.maxsize
     934    ) -> int:
     935        # << Official documentation >>
     936        """Return zero-based index in the vec of the first item whose value is equal to `item`.
     937        Raises a ValueError if there is no such item.
     938
     939        Example
     940        -------
     941        ```py
     942        vec = Vec((1, 2, 3))
     943        assert vec.index(2) == 1
     944        ```
     945        """
     946        if self._ptr is None:
     947            raise ValueError from None
     948
     949        return self._ptr.index(item, start, end)
     950
     951    def count(self, item: T) -> int:
     952        """Return the number of occurrences of `item` in the vec.
     953
     954        `0` is returned if the vector is empty or hasn't been initialized, as well if them item not found.
     955
     956        Example
     957        --------
     958        ```py
     959        vec = Vec((1, 2, 3, 3))
     960        assert vec.count(3) == 2
     961        ```
     962        """
     963        if self._ptr is None:
     964            return 0
     965
     966        return self._ptr.count(item)
     967
     968    def __len__(self) -> int:
     969        return len(self._ptr) if self._ptr else 0
     970
     971    def __setitem__(self, index: int, value: T):
     972        if not self._ptr:
     973            raise IndexError from None
     974
     975        self._ptr[index] = value
     976
     977    @typing.overload
     978    def __getitem__(self, index: slice) -> Vec[T]: ...
     979
     980    @typing.overload
     981    def __getitem__(self, index: int) -> T: ...
     982
     983    def __getitem__(self, index: int | slice) -> T | Vec[T]:
     984        if not self._ptr:
     985            raise IndexError("Index out of range")
     986
     987        if isinstance(index, slice):
     988            return Vec(self._ptr[index])
     989
     990        return self._ptr[index]
     991
     992    def __delitem__(self, index: int) -> None:
     993        if not self._ptr:
     994            return
     995
     996        del self._ptr[index]
     997
     998    def __contains__(self, element: T) -> bool:
     999        return element in self._ptr if self._ptr else False
    1000
    1001    def __iter__(self) -> collections.Iterator[T]:
    1002        if self._ptr is None:
    1003            return iter(())
    1004
    1005        return self._ptr.__iter__()
    1006
    1007    def __repr__(self) -> str:
    1008        return "[]" if not self._ptr else repr(self._ptr)
    1009
    1010    def __eq__(self, other: Vec[T] | list[T]) -> bool:
    1011        if isinstance(other, Vec):
    1012            return self._ptr == other._ptr
    1013
    1014        return self._ptr == other
    1015
    1016    def __ne__(self, other: Vec[T] | list[T]) -> bool:
    1017        return not self.__eq__(other)
    1018
    1019    def __le__(self, other: list[T]) -> bool:
    1020        if not self._ptr:
    1021            return False
    1022
    1023        return self._ptr <= other
    1024
    1025    def __ge__(self, other: list[T]) -> bool:
    1026        if not self._ptr:
    1027            return False
    1028
    1029        return self._ptr >= other
    1030
    1031    def __lt__(self, other: list[T]) -> bool:
    1032        if not self._ptr:
    1033            return False
    1034
    1035        return self._ptr < other
    1036
    1037    def __gt__(self, other: list[T]) -> bool:
    1038        if not self._ptr:
    1039            return False
    1040
    1041        return self._ptr > other
    1042
    1043    def __bool__(self) -> bool:
    1044        return bool(self._ptr)
    1045
    1046    def __reversed__(self) -> collections.Iterator[T]:
    1047        return reversed(self._ptr or ())

A contiguous growable alternative to builtin `list` with extra functionalities.

The layout of `Vec<T>` is exactly the same as `list<T>`. Which means `list<T>`'s methods are inherited into `Vec<T>`.

###### Example

    names = Vec()
    names.push('foo')
    names.push('bar')

    print(names) # ['foo', 'bar']
    assert names.len() == 2

###### Constructing

- `Vec()`: Create an empty vec, this will not allocate the initial buffer.
- `Vec(other_list)`: Create a vec which points to `other_list`
- `Vec([1, 2, 3])`: Create a vec with `[1, 2, 3]` pre-allocated.
- `Vec(iterable)`: Create a vec from an `iterable`, This is `O(n)` where `n` is the number of elements, since it copies `iterable`'s elements into a new list.
- `Vec.with_capacity(5)`: Create a vec that can hold up to 5 elements

## Iterating over `Vec`

There're two ways to iterate over a `Vec`. The first is to normally use `for` loop.

    for i in names:
        print(i)

    # foo
    # bar

The second is to use `Vec.iter`, which yields all items in this `Vec` from start to end. Then the iterator gets exhausted as usual, See `sain.Iterator`.

    iterator = names.iter()
    for name in iterator.map(str.upper):
        print(name)

    # FOO
    # BAR

    # No more items, The actual vec is left unchanged.
    assert iterator.next().is_none()

## Comparison operators

A `Vec` may be compared with another `Vec` or a `list`, any other type will return `False`

    vec = Vec([1, 2, 3])
    assert vec == [1, 2, 3] # True
    assert vec != (1, 2, 3)

## Zero-Copy

A vec that gets initialized from a `list` will point to it and doesn't copy it. So any element that gets appended to the list will also get pushed into the vec that's pointing to it and vice-versa.

    cells: list[str] = []
    vec = Vec(cells) # This DOES NOT copy the `cells`.

    cells.append("foo")
    vec[0] == "foo"  # True

The opposite of the above is to initialize the vec from either an iterable or args, or copy the list.

    from sain.collections import vec, Vec

    # Copy the list into a vec.
    vec = Vec(cells[:])
    cells.append("bar")

    vec[1] # IndexError: "bar" doesn't exist in vec.

# Implementations

This class implements Vec in Rust.

Vec(iterable: Iterable[~T] | None = None) View Source

    170    def __init__(self, iterable: collections.Iterable[T] | None = None) -> None:
    171        """Create an empty `Vec<T>`.
    172
    173        The vector will not allocate until elements are pushed onto it.
    174
    175        Example
    176        ------
    177        ```py
    178        vec: Vec[float] = Vec()
    179        ```
    180        """
    181        # We won't allocate to build the list here.
    182        # Instead, On first push or fist indexed set
    183        # we allocate if it was None.
    184        if isinstance(iterable, list):
    185            # Calling `list()` on another list will copy it, So instead we just point to it.
    186            self._ptr = iterable
    187        elif isinstance(iterable, Vec):
    188            self._ptr = iterable._ptr
    189        # any other iterable that ain't a list needs to get copied into a new list.
    190        else:
    191            self._ptr: list[T] | None = list(iterable) if iterable else None
    192
    193        self._capacity: int | None = None

Create an empty `Vec<T>`.

The vector will not allocate until elements are pushed onto it.

###### Example

    vec: Vec[float] = Vec()

@classmethod
def with_capacity(cls, capacity: int) -> Vec[~T]: View Source

    195    @classmethod
    196    def with_capacity(cls, capacity: int) -> Vec[T]:
    197        """Create a new `Vec` with at least the specified capacity.
    198        This vec will be able to hold `capacity` elements without pushing further.
    199
    200        Check out `Vec.push_within_capacity` as well.
    201
    202        Example
    203        -------
    204        ```py
    205        vec = Vec.with_capacity(3)
    206        assert vec.len() == 0 and vec.capacity() >= 3
    207
    208        vec.push(1)
    209        vec.push(2)
    210        vec.push(3)
    211        print(vec.len()) # 3
    212
    213        # This won't push.
    214        vec.push(4)
    215        ```
    216        """
    217        v = cls()
    218        v._capacity = capacity
    219        return v

Create a new `Vec` with at least the specified capacity. This vec will be able to hold `capacity` elements without pushing further.

Check out `Vec.push_within_capacity` as well.

###### Example

    vec = Vec.with_capacity(3)
    assert vec.len() == 0 and vec.capacity() >= 3

    vec.push(1)
    vec.push(2)
    vec.push(3)
    print(vec.len()) # 3

    # This won't push.
    vec.push(4)

def as_ref(self) -> sain.collections.slice.Slice[~T]: View Source

    221    def as_ref(self) -> Slice[T]:
    222        """Return an immutable view over this vector elements.
    223
    224        No copying occurs.
    225
    226        Example
    227        -------
    228        ```py
    229        def send_bytes(v: Slice[int]) -> None:
    230            # access `vec` in a read-only mode.
    231            socket.write_all(v)
    232
    233        buf = Vec([1, 2, 3])
    234        send_bytes(buf.as_ref())
    235        ```
    236        """
    237        return Slice(self)

Return an immutable view over this vector elements.

No copying occurs.

###### Example

    def send_bytes(v: Slice[int]) -> None:
        # access `vec` in a read-only mode.
        socket.write_all(v)

    buf = Vec([1, 2, 3])
    send_bytes(buf.as_ref())

def as_mut(self) -> sain.collections.slice.SliceMut[~T]: View Source

    239    def as_mut(self) -> SliceMut[T]:
    240        """Return a mutable view over this vector elements.
    241
    242        No copying occurs.
    243
    244        Example
    245        -------
    246        ```py
    247        def read_bytes(buf: SliceMut[int]) -> None:
    248            socket.read_to_end(buf.as_mut())
    249
    250        buf: Vec[int] = Vec()
    251        read_bytes(buf.as_mut()) # or just `buf`
    252        assert vec.len() >= 1
    253        ```
    254        """
    255        return SliceMut(self)

Return a mutable view over this vector elements.

No copying occurs.

###### Example

    def read_bytes(buf: SliceMut[int]) -> None:
        socket.read_to_end(buf.as_mut())

    buf: Vec[int] = Vec()
    read_bytes(buf.as_mut()) # or just `buf`
    assert vec.len() >= 1

def len(self) -> int: View Source

    257    def len(self) -> int:
    258        """Return the number of elements in this vector.
    259
    260        Example
    261        -------
    262        ```py
    263        vec = Vec((1,2,3))
    264
    265        assert vec.len() == 3
    266        ```
    267        """
    268        return self.__len__()

Return the number of elements in this vector.

###### Example

    vec = Vec((1,2,3))

    assert vec.len() == 3

def capacity(self) -> int: View Source

    270    def capacity(self) -> int:
    271        """Return the capacity of this vector if set, 0 if not .
    272
    273        The number `0` here has two different Meanings:
    274        - The first means the `Vec` doesn't have a specific capacity set.
    275        - The second means the `Vec` literally initialized with `0` capacity.
    276
    277        Example
    278        -------
    279        ```py
    280        vec_with_cap = Vec.with_capacity(3)
    281        assert vec_with_cap.capacity().unwrap() == 3
    282
    283        vec = Vec([1, 2, 3])
    284        assert vec.capacity() == 0
    285        ```
    286        """
    287        return 0 if self._capacity is None else self._capacity

Return the capacity of this vector if set, 0 if not .

The number `0` here has two different Meanings:

- The first means the `Vec` doesn't have a specific capacity set.
- The second means the `Vec` literally initialized with `0` capacity.

###### Example

    vec_with_cap = Vec.with_capacity(3)
    assert vec_with_cap.capacity().unwrap() == 3

    vec = Vec([1, 2, 3])
    assert vec.capacity() == 0

def iter(self) -> sain.iter.TrustedIter[~T]: View Source

    289    def iter(self) -> _iter.TrustedIter[T]:
    290        """Returns an iterator over this vector elements.
    291
    292        Example
    293        -------
    294        ```py
    295        vec = Vec([1 ,2, 3])
    296        for element in vec.iter().map(str):
    297            print(element)
    298        ```
    299        """
    300        return _iter.TrustedIter(self._ptr or ())

Returns an iterator over this vector elements.

###### Example

    vec = Vec([1 ,2, 3])
    for element in vec.iter().map(str):
        print(element)

def is_empty(self) -> bool: View Source

    302    def is_empty(self) -> bool:
    303        """Returns true if the vector contains no elements.
    304
    305        Inlined into:
    306        ```py
    307        not self.vec
    308        ```
    309        """
    310        return not self._ptr

Returns true if the vector contains no elements.

Inlined into:

    not self.vec

def leak(self) -> list[~T]: View Source

    312    def leak(self) -> list[T]:
    313        """Consumes and leaks the Vec, returning a mutable reference to the contents.
    314
    315        After calling this, this vec will no longer reference the underlying buffer,
    316        therefore, it becomes unusable.
    317
    318        if `self` is uninitialized, an empty list is returned.
    319
    320        This function is only useful when you want to detach from a `Vec<T>` and get a `list[T]` without
    321        any copies.
    322
    323        Example
    324        -------
    325        ```py
    326        x = Vec([1, 2, 3])
    327        owned = x.leak()
    328        # x is now unusable.
    329        owned[0] += 1
    330        assert owned == [2, 2, 3]
    331        ```
    332        """
    333        if self._ptr is not None:
    334            # don't point to `_ptr` anymore.
    335            tmp = self._ptr
    336            del self._ptr
    337            return tmp
    338
    339        return []

Consumes and leaks the Vec, returning a mutable reference to the contents.

After calling this, this vec will no longer reference the underlying buffer, therefore, it becomes unusable.

if `self` is uninitialized, an empty list is returned.

This function is only useful when you want to detach from a `Vec<T>` and get a `list[T]` without any copies.

###### Example

    x = Vec([1, 2, 3])
    owned = x.leak()
    # x is now unusable.
    owned[0] += 1
    assert owned == [2, 2, 3]

def split_off(self, at: int) -> Vec[~T]: View Source

    341    def split_off(self, at: int) -> Vec[T]:
    342        """Split the vector off at the specified position, returning a new
    343        vec at the range of `[at : len]`, leaving `self` at `[at : vec_len]`.
    344
    345        if this vec is empty, `self` is returned unchanged.
    346
    347        Example
    348        -------
    349        ```py
    350        origin = Vec((1, 2, 3, 4))
    351        split = vec.split_off(2)
    352
    353        print(origin, split)  # [1, 2], [3, 4]
    354        ```
    355
    356        Raises
    357        ------
    358        `IndexError`
    359            This method will raise if `at` > `len(self)`
    360        """
    361        len_ = self.len()
    362        if at > len_:
    363            raise IndexError(
    364                f"Index `at` ({at}) should be <= than len of vector ({len_}) "
    365            ) from None
    366
    367        # Either the list is empty or uninit.
    368        if not self._ptr:
    369            return self
    370
    371        split = self[at:len_]  # split the items into a new vec.
    372        del self._ptr[at:len_]  # remove the items from the original list.
    373        return split

Split the vector off at the specified position, returning a new vec at the range of `[at : len]`, leaving `self` at `[at : vec_len]`.

if this vec is empty, `self` is returned unchanged.

###### Example

    origin = Vec((1, 2, 3, 4))
    split = vec.split_off(2)

    print(origin, split)  # [1, 2], [3, 4]

###### Raises

- `IndexError`: This method will raise if `at` > `len(self)`

def split_first(self) -> '_option.Option[tuple[T, collections.Sequence[T]]]': View Source

    375    def split_first(self) -> _option.Option[tuple[T, collections.Sequence[T]]]:
    376        """Split the first and rest elements of the vector, If empty, `None` is returned.
    377
    378        Example
    379        -------
    380        ```py
    381        vec = Vec([1, 2, 3])
    382        split = vec.split_first()
    383        assert split == Some((1, [2, 3]))
    384
    385        vec: Vec[int] = Vec()
    386        split = vec.split_first()
    387        assert split.is_none()
    388        ```
    389        """
    390        if not self._ptr:
    391            return _option.NOTHING
    392
    393        # optimized to only one element in the vector.
    394        if self.len() == 1:
    395            return _option.Some((self[0], ()))
    396
    397        first, *rest = self._ptr
    398        return _option.Some((first, rest))

Split the first and rest elements of the vector, If empty, `None` is returned.

###### Example

    vec = Vec([1, 2, 3])
    split = vec.split_first()
    assert split == Some((1, [2, 3]))

    vec: Vec[int] = Vec()
    split = vec.split_first()
    assert split.is_none()

def split_last(self) -> '_option.Option[tuple[T, collections.Sequence[T]]]': View Source

    400    def split_last(self) -> _option.Option[tuple[T, collections.Sequence[T]]]:
    401        """Split the last and rest elements of the vector, If empty, `None` is returned.
    402
    403        Example
    404        -------
    405        ```py
    406        vec = Vec([1, 2, 3])
    407        last, rest = vec.split_last().unwrap()
    408        assert (last, rest) == [3, [1, 2]]
    409        ```
    410        """
    411        if not self._ptr:
    412            return _option.NOTHING
    413
    414        # optimized to only one element in the vector.
    415        if self.len() == 1:
    416            return _option.Some((self[0], ()))
    417
    418        last, *rest = self._ptr[-1], *self._ptr[:-1]
    419        return _option.Some((last, rest))

Split the last and rest elements of the vector, If empty, `None` is returned.

###### Example

    vec = Vec([1, 2, 3])
    last, rest = vec.split_last().unwrap()
    assert (last, rest) == [3, [1, 2]]

def split_at( self, mid: int) -> tuple[Vec[~T], Vec[~T]]: View Source

    421    def split_at(self, mid: int) -> tuple[Vec[T], Vec[T]]:
    422        """Divide `self` into two at an index.
    423
    424        The first will contain all elements from `[0:mid]` excluding `mid` it self.
    425        and the second will contain the remaining elements.
    426
    427        if `mid` > `self.len()`, Then all elements will be moved to the left,
    428        returning an empty vec in right.
    429
    430        Example
    431        -------
    432        ```py
    433        buffer = Vec((1, 2, 3, 4))
    434        left, right = buffer.split_at(0)
    435        assert left == [] and right == [1, 2, 3, 4]
    436
    437        left, right = buffer.split_at(2)
    438        assert left == [1, 2] and right == [2, 3]
    439        ```
    440
    441        The is roughly the implementation
    442        ```py
    443        vec[0:mid], vec[mid:]
    444        ```
    445        """
    446        return self[0:mid], self[mid:]

Divide `self` into two at an index.

The first will contain all elements from `[0:mid]` excluding `mid` it self. and the second will contain the remaining elements.

if `mid` > `self.len()`, Then all elements will be moved to the left, returning an empty vec in right.

###### Example

    buffer = Vec((1, 2, 3, 4))
    left, right = buffer.split_at(0)
    assert left == [] and right == [1, 2, 3, 4]

    left, right = buffer.split_at(2)
    assert left == [1, 2] and right == [2, 3]

The is roughly the implementation

    vec[0:mid], vec[mid:]

def swap(self, a: int, b: int): View Source

    448    def swap(self, a: int, b: int):
    449        """Swap two elements in the vec.
    450
    451        if `a` equals to `b` then it's guaranteed that elements won't change value.
    452
    453        Example
    454        -------
    455        ```py
    456        buf = Vec([1, 2, 3, 4])
    457        buf.swap(0, 3)
    458        assert buf == [4, 2, 3, 1]
    459        ```
    460
    461        Raises
    462        ------
    463        IndexError
    464            If the positions of `a` or `b` are out of index.
    465        """
    466        if self[a] == self[b]:
    467            return
    468
    469        self[a], self[b] = self[b], self[a]

Swap two elements in the vec.

if `a` equals to `b` then it's guaranteed that elements won't change value.

###### Example

    buf = Vec([1, 2, 3, 4])
    buf.swap(0, 3)
    assert buf == [4, 2, 3, 1]

###### Raises

- IndexError: If the positions of `a` or `b` are out of index.

def swap_unchecked(self, a: int, b: int): View Source

    471    def swap_unchecked(self, a: int, b: int):
    472        """Swap two elements in the vec. without checking if `a` == `b`.
    473
    474        If you care about `a` and `b` equality, see `Vec.swap`.
    475
    476        Example
    477        -------
    478        ```py
    479        buf = Vec([1, 2, 3, 1])
    480        buf.swap_unchecked(0, 3)
    481        assert buf == [1, 2, 3, 1]
    482        ```
    483
    484        Raises
    485        ------
    486        IndexError
    487            If the positions of `a` or `b` are out of index.
    488        """
    489        self[a], self[b] = self[b], self[a]

Swap two elements in the vec. without checking if `a` == `b`.

If you care about `a` and `b` equality, see `Vec.swap`.

###### Example

    buf = Vec([1, 2, 3, 1])
    buf.swap_unchecked(0, 3)
    assert buf == [1, 2, 3, 1]

###### Raises

- IndexError: If the positions of `a` or `b` are out of index.

def first(self) -> '_option.Option[T]': View Source

    491    def first(self) -> _option.Option[T]:
    492        """Get the first element in this vec, returning `None` if there's none.
    493
    494        Example
    495        -------
    496        ```py
    497        vec = Vec((1,2,3))
    498        first = vec.first()
    499        assert ~first == 1
    500        ```
    501        """
    502        return self.get(0)

Get the first element in this vec, returning `None` if there's none.

###### Example

    vec = Vec((1,2,3))
    first = vec.first()
    assert ~first == 1

def last(self) -> '_option.Option[T]': View Source

    504    def last(self) -> _option.Option[T]:
    505        """Get the last element in this vec, returning `None` if there's none.
    506
    507        Example
    508        -------
    509        ```py
    510        vec = Vec([1, 2, 3, 4])
    511        first = vec.last()
    512        assert ~first == 4
    513        ```
    514        """
    515        return self.get(-1)

Get the last element in this vec, returning `None` if there's none.

###### Example

    vec = Vec([1, 2, 3, 4])
    first = vec.last()
    assert ~first == 4

def truncate(self, size: int) -> None: View Source

    517    def truncate(self, size: int) -> None:
    518        """Shortens the vec, keeping the first `size` elements and dropping the rest.
    519
    520        Example
    521        -------
    522        ```py
    523        vec = Vec([1,2,3])
    524        vec.truncate(1)
    525        assert vec == [1]
    526        ```
    527        """
    528        if not self._ptr:
    529            return
    530
    531        del self._ptr[size:]

Shortens the vec, keeping the first `size` elements and dropping the rest.

###### Example

    vec = Vec([1,2,3])
    vec.truncate(1)
    assert vec == [1]

def retain(self, f: Callable[[~T], bool]) -> None: View Source

    533    def retain(self, f: collections.Callable[[T], bool]) -> None:
    534        """Retains only the elements specified by the predicate.
    535
    536        This operation occurs in-place without copying the original list.
    537
    538        Example
    539        -------
    540        ```py
    541        vec = Vec([1, 2, 3])
    542        vec.retain(lambda elem: elem > 1)
    543
    544        assert vec == [2, 3]
    545        ```
    546
    547        The impl for this method is very simple
    548        ```py
    549        for idx, e in enumerate(vec):
    550            if not f(e):
    551                del vec[idx]
    552        ```
    553        """
    554        if not self._ptr:
    555            return
    556
    557        idx = 0
    558        while idx < len(self._ptr):
    559            if not f(self._ptr[idx]):
    560                del self._ptr[idx]
    561            else:
    562                idx += 1

Retains only the elements specified by the predicate.

This operation occurs in-place without copying the original list.

###### Example

    vec = Vec([1, 2, 3])
    vec.retain(lambda elem: elem > 1)

    assert vec == [2, 3]

The impl for this method is very simple

    for idx, e in enumerate(vec):
        if not f(e):
            del vec[idx]

def swap_remove(self, item: ~T) -> ~T: View Source

    564    def swap_remove(self, item: T) -> T:
    565        """Remove the first appearance of `item` from this vector and return it.
    566
    567        Raises
    568        ------
    569        * `ValueError`: if `item` is not in this vector.
    570        * `MemoryError`: if this vector hasn't allocated, Aka nothing has been pushed to it.
    571
    572        Example
    573        -------
    574        ```py
    575        vec = Vec(('a', 'b', 'c'))
    576        element = vec.remove('a')
    577        assert vec == ['b', 'c'] and element == 'a'
    578        ```
    579        """
    580        if self._ptr is None:
    581            raise MemoryError("Vec is unallocated.") from None
    582
    583        return self._ptr.pop(self.index(item))

Remove the first appearance of `item` from this vector and return it.

###### Raises

- * `ValueError` (if `item` is not in this vector.):

- * `MemoryError` (if this vector hasn't allocated, Aka nothing has been pushed to it.):

###### Example

    vec = Vec(('a', 'b', 'c'))
    element = vec.remove('a')
    assert vec == ['b', 'c'] and element == 'a'

def fill(self, value: ~T) -> None: View Source

    585    def fill(self, value: T) -> None:
    586        """Fill `self` with the given `value`.
    587
    588        Nothing happens if the vec is empty or unallocated.
    589
    590        Example
    591        ```py
    592        a = Vec([0, 1, 2, 3])
    593        a.fill(0)
    594        assert a == [0, 0, 0, 0]
    595        ```
    596        """
    597        if not self._ptr:
    598            return
    599
    600        for n, _ in enumerate(self):
    601            self[n] = value

Fill `self` with the given `value`.

Nothing happens if the vec is empty or unallocated.

Example

    a = Vec([0, 1, 2, 3])
    a.fill(0)
    assert a == [0, 0, 0, 0]

def push(self, item: ~T) -> None: View Source

    603    def push(self, item: T) -> None:
    604        """Push an element at the end of the vector.
    605
    606        Example
    607        -------
    608        ```py
    609        vec = Vec()
    610        vec.push(1)
    611
    612        assert vec == [1]
    613        ```
    614        """
    615        if self._capacity is not None:
    616            self.push_within_capacity(item)
    617            return
    618
    619        if self._ptr is None:
    620            self._ptr = []
    621
    622        self._ptr.append(item)

Push an element at the end of the vector.

###### Example

    vec = Vec()
    vec.push(1)

    assert vec == [1]

def push_within_capacity(self, x: ~T) -> 'Result[None, T]': View Source

    624    def push_within_capacity(self, x: T) -> Result[None, T]:
    625        """Appends an element if there is sufficient spare capacity, otherwise an error is returned with the element.
    626
    627        Example
    628        -------
    629        ```py
    630        vec: Vec[int] = Vec.with_capacity(3)
    631        for i in range(3):
    632            match vec.push_within_capacity(i):
    633                case Ok(_):
    634                    print("All good.")
    635                case Err(elem):
    636                    print("Reached max cap :< can't push", elem)
    637        ```
    638
    639        Or you can also just call `Vec.push` and it will push if there's is sufficient capacity.
    640        ```py
    641        vec: Vec[int] = Vec.with_capacity(3)
    642
    643        vec.extend((1, 2, 3))
    644        vec.push(4)
    645
    646        assert vec.len() == 3
    647        ```
    648        """
    649        if self._ptr is None:
    650            self._ptr = []
    651
    652        if self.len() == self._capacity:
    653            return _result.Err(x)
    654
    655        self._ptr.append(x)
    656        return _result.Ok(None)

Appends an element if there is sufficient spare capacity, otherwise an error is returned with the element.

###### Example

    vec: Vec[int] = Vec.with_capacity(3)
    for i in range(3):
        match vec.push_within_capacity(i):
            case Ok(_):
                print("All good.")
            case Err(elem):
                print("Reached max cap :< can't push", elem)

Or you can also just call `Vec.push` and it will push if there's is sufficient capacity.

    vec: Vec[int] = Vec.with_capacity(3)

    vec.extend((1, 2, 3))
    vec.push(4)

    assert vec.len() == 3

def reserve(self, additional: int) -> None: View Source

    658    def reserve(self, additional: int) -> None:
    659        """Reserves capacity for at least additional more elements to be inserted in the given Vec<T>.
    660
    661        Example
    662        -------
    663        ```py
    664        vec = Vec.with_capacity(3)
    665        is_vip = random.choice((True, False))
    666
    667        for i in range(4):
    668            match vec.push_within_capacity(i):
    669                case Ok(_):
    670                    print("All good")
    671                case Err(person):
    672                    # If the person is a VIP, then reserve for one more.
    673                    if is_vip:
    674                        vec.reserve(1)
    675                        continue
    676
    677                    # is_vip was false.
    678                    print("Can't reserve for non-VIP members...", person)
    679                    break
    680        ```
    681        """
    682        if self._capacity is not None:
    683            self._capacity += additional

Reserves capacity for at least additional more elements to be inserted in the given Vec.

###### Example

    vec = Vec.with_capacity(3)
    is_vip = random.choice((True, False))

    for i in range(4):
        match vec.push_within_capacity(i):
            case Ok(_):
                print("All good")
            case Err(person):
                # If the person is a VIP, then reserve for one more.
                if is_vip:
                    vec.reserve(1)
                    continue

                # is_vip was false.
                print("Can't reserve for non-VIP members...", person)
                break

def shrink_to_fit(self) -> None: View Source

    685    def shrink_to_fit(self) -> None:
    686        """Shrink the capacity of this `Vec` to match its length.
    687
    688        If `self` is initialized with no capacity, This is a `NOP`.
    689
    690        Example
    691        -------
    692        ```py
    693        s = Vec([1, 2, 3, 4])
    694
    695        s.reserve(100)
    696        s.shrink_to_fit()
    697        assert s.capacity() == 4
    698        ```
    699        """
    700        if self._capacity is None:
    701            return
    702
    703        # The capacity is never less than the length.
    704        self._capacity = min(self.__len__(), self._capacity)

Shrink the capacity of this `Vec` to match its length.

If `self` is initialized with no capacity, This is a `NOP`.

###### Example

    s = Vec([1, 2, 3, 4])

    s.reserve(100)
    s.shrink_to_fit()
    assert s.capacity() == 4

def shrink_to(self, min_capacity: int) -> None: View Source

    706    def shrink_to(self, min_capacity: int) -> None:
    707        """Shrink the capacity of this `Vec` to a minimum specified capacity.
    708
    709        If `self` is initialized with no capacity or the current capacity is less than the lower limit,
    710        This is a `NOP`.
    711
    712        Example
    713        -------
    714        ```py
    715        vec = Vec.with_capacity(10)
    716        vec.extend([1, 2, 3])
    717        assert vec.capacity() >= 10
    718        vec.shrink_to(4)
    719        assert vec.capacity() >= 4
    720        vec.shrink_to(0)
    721        ```
    722        """
    723        if self._capacity is None or self._capacity <= min_capacity:
    724            return
    725
    726        # Ensure the capacity is not reduced below the current length of the vector.
    727        self._capacity = max(self.__len__(), min_capacity)

Shrink the capacity of this `Vec` to a minimum specified capacity.

If `self` is initialized with no capacity or the current capacity is less than the lower limit, This is a `NOP`.

###### Example

    vec = Vec.with_capacity(10)
    vec.extend([1, 2, 3])
    assert vec.capacity() >= 10
    vec.shrink_to(4)
    assert vec.capacity() >= 4
    vec.shrink_to(0)

def append(self, value: ~T) -> None: View Source

    733    def append(self, value: T) -> None:
    734        """An alias to `Vec.push`."""
    735        self.push(value)

An alias to `Vec.push`.

def get(self, index: int) -> '_option.Option[T]': View Source

    737    def get(self, index: int) -> _option.Option[T]:
    738        """Get the item at the given index, or `Some[None]` if its out of bounds.
    739
    740        Example
    741        -------
    742        ```py
    743        vec = Vec((1, 2, 3))
    744        vec.get(0) == Some(1)
    745        vec.get(3) == Some(None)
    746        ```
    747        """
    748        try:
    749            return _option.Some(self[index])
    750        except IndexError:
    751            return _option.NOTHING

Get the item at the given index, or `Some[None]` if its out of bounds.

###### Example

    vec = Vec((1, 2, 3))
    vec.get(0) == Some(1)
    vec.get(3) == Some(None)

def insert(self, index: int, value: ~T) -> None: View Source

    753    def insert(self, index: int, value: T) -> None:
    754        """Insert an element at the position `index`.
    755
    756        Example
    757        --------
    758        ```py
    759        vec = Vec((2, 3))
    760        vec.insert(0, 1)
    761        assert vec == [1, 2, 3]
    762        ```
    763        """
    764        self.__setitem__(index, value)

Insert an element at the position `index`.

###### Example

    vec = Vec((2, 3))
    vec.insert(0, 1)
    assert vec == [1, 2, 3]

def pop(self, index: int = -1) -> '_option.Option[T]': View Source

    766    def pop(self, index: int = -1) -> _option.Option[T]:
    767        """Removes the last element from a vector and returns it, or `None` if it is empty.
    768
    769        Example
    770        -------
    771        ```py
    772        vec = Vec((1, 2, 3))
    773        assert vec.pop() == Some(3)
    774        assert vec == [1, 2]
    775        ```
    776        """
    777        if not self._ptr:
    778            return _option.NOTHING
    779
    780        return _option.Some(self._ptr.pop(index))

Removes the last element from a vector and returns it, or `None` if it is empty.

###### Example

    vec = Vec((1, 2, 3))
    assert vec.pop() == Some(3)
    assert vec == [1, 2]

def pop_if(self, pred: Callable[[~T], bool]) -> '_option.Option[T]': View Source

    782    def pop_if(self, pred: collections.Callable[[T], bool]) -> _option.Option[T]:
    783        """Removes the last element from a vector and returns it if `f` returns `True`,
    784        or `None` if it is empty.
    785
    786        Example
    787        -------
    788        ```py
    789        vec = Vec((1, 2, 3))
    790        assert vec.pop_if(lambda num: num * 2 == 6) == Some(3)
    791        assert vec == [1, 2]
    792        ```
    793        """
    794        if not self._ptr:
    795            return _option.NOTHING
    796
    797        if pred(self[-1]):
    798            return self.pop()
    799
    800        return _option.NOTHING

Removes the last element from a vector and returns it if `f` returns `True`, or `None` if it is empty.

###### Example

    vec = Vec((1, 2, 3))
    assert vec.pop_if(lambda num: num * 2 == 6) == Some(3)
    assert vec == [1, 2]

def dedup(self) -> None: View Source

    802    def dedup(self) -> None:
    803        """Removes consecutive repeated elements in the vector according to their `__eq__`
    804        implementation.
    805
    806        Example
    807        -------
    808        ```py
    809        vec = Vec([1, 2, 2, 3, 2])
    810        vec.dedup()
    811        assert vec == [1, 2, 3, 2]
    812        """
    813        self.dedup_by(lambda a, b: a == b)

Removes consecutive repeated elements in the vector according to their `__eq__` implementation.

###### Example

```py vec = Vec([1, 2, 2, 3, 2]) vec.dedup() assert vec == [1, 2, 3, 2]

def dedup_by(self, same_bucket: Callable[[~T, ~T], bool]) -> None: View Source

    815    def dedup_by(self, same_bucket: collections.Callable[[T, T], bool]) -> None:
    816        """Removes all but the first of consecutive elements in the vector satisfying a given equality.
    817
    818        Example
    819        -------
    820        ```py
    821        vec = Vec(["foo", "bar", "Bar", "baz", "bar"])
    822        vec.dedup_by(lambda a, b: a.lower() == b.lower())
    823        assert vec == ["foo", "bar", "baz", "bar"]
    824        ```
    825
    826        Only remove consecutive duplicates.
    827        ```py
    828        vec = Vec([1, 2, 2, 3, 4, 1])
    829        vec.dedup_by(lambda a, b: a == b)
    830        # The final 1 is not adjacent to the first 1, so it is not removed.
    831        assert vec == [1, 2, 3, 4, 1]
    832        ```
    833        """
    834
    835        if not self._ptr or (len_ := len(self._ptr)) <= 1:
    836            return
    837
    838        idx = 1
    839        while idx < len_:
    840            if same_bucket(self._ptr[idx], self._ptr[idx - 1]):
    841                del self._ptr[idx]
    842                len_ -= 1
    843            else:
    844                idx += 1

Removes all but the first of consecutive elements in the vector satisfying a given equality.

###### Example

    vec = Vec(["foo", "bar", "Bar", "baz", "bar"])
    vec.dedup_by(lambda a, b: a.lower() == b.lower())
    assert vec == ["foo", "bar", "baz", "bar"]

Only remove consecutive duplicates.

    vec = Vec([1, 2, 2, 3, 4, 1])
    vec.dedup_by(lambda a, b: a == b)
    # The final 1 is not adjacent to the first 1, so it is not removed.
    assert vec == [1, 2, 3, 4, 1]

def remove(self, item: ~T) -> None: View Source

    846    def remove(self, item: T) -> None:
    847        """Remove the first appearance of `item` from this vector.
    848
    849        Example
    850        -------
    851        ```py
    852        vec = Vec(('a', 'b', 'c'))
    853        vec.remove('a')
    854        assert vec == ['b', 'c']
    855        ```
    856        """
    857        if not self._ptr:
    858            return
    859
    860        self._ptr.remove(item)

Remove the first appearance of `item` from this vector.

###### Example

    vec = Vec(('a', 'b', 'c'))
    vec.remove('a')
    assert vec == ['b', 'c']

def extend(self, iterable: Iterable[~T]) -> None: View Source

    862    def extend(self, iterable: collections.Iterable[T]) -> None:
    863        """Extend this vector from another iterable.
    864
    865        Example
    866        -------
    867        ```py
    868        vec = Vec((1, 2, 3))
    869        vec.extend((4, 5, 6))
    870
    871        assert vec == [1, 2, 3, 4, 5, 6]
    872        ```
    873        """
    874        if self._ptr is None:
    875            self._ptr = []
    876
    877        self._ptr.extend(iterable)

Extend this vector from another iterable.

###### Example

    vec = Vec((1, 2, 3))
    vec.extend((4, 5, 6))

    assert vec == [1, 2, 3, 4, 5, 6]

def copy(self) -> Vec[~T]: View Source

    879    def copy(self) -> Vec[T]:
    880        """Copy all elements of `self` into a new vector.
    881
    882        Example
    883        -------
    884        ```py
    885        original = Vec((1,2,3))
    886        copy = original.copy()
    887        copy.push(4)
    888
    889        print(original) # [1, 2, 3]
    890        ```
    891        """
    892        return Vec(self._ptr[:]) if self._ptr else Vec()

Copy all elements of `self` into a new vector.

###### Example

    original = Vec((1,2,3))
    copy = original.copy()
    copy.push(4)

    print(original) # [1, 2, 3]

def clear(self) -> None: View Source

    894    def clear(self) -> None:
    895        """Clear all elements of this vector.
    896
    897        Example
    898        -------
    899        ```py
    900        vec = Vec((1,2,3))
    901        vec.clear()
    902        assert vec.len() == 0
    903        ```
    904        """
    905        if not self._ptr:
    906            return
    907
    908        self._ptr.clear()

Clear all elements of this vector.

###### Example

    vec = Vec((1,2,3))
    vec.clear()
    assert vec.len() == 0

def sort( self, *, key: 'collections.Callable[[T], SupportsRichComparison] | None' = None, reverse: bool = False) -> None: View Source

    910    def sort(
    911        self,
    912        *,
    913        key: collections.Callable[[T], SupportsRichComparison] | None = None,
    914        reverse: bool = False,
    915    ) -> None:
    916        """This method sorts the list in place, using only < comparisons between items.
    917
    918        Example
    919        -------
    920        ```py
    921        vec = Vec((2, 1, 3))
    922        vec.sort()
    923        assert vec == [1, 2, 3]
    924        ```
    925        """
    926        if not self._ptr:
    927            return
    928
    929        # key can be `None` here just fine, idk why pyright is complaining.
    930        self._ptr.sort(key=key, reverse=reverse)  # pyright: ignore

This method sorts the list in place, using only < comparisons between items.

###### Example

    vec = Vec((2, 1, 3))
    vec.sort()
    assert vec == [1, 2, 3]

def index( self, item: ~T, start: <class 'SupportsIndex'> = 0, end: int = 9223372036854775807) -> int: View Source

    932    def index(
    933        self, item: T, start: typing.SupportsIndex = 0, end: int = _sys.maxsize
    934    ) -> int:
    935        # << Official documentation >>
    936        """Return zero-based index in the vec of the first item whose value is equal to `item`.
    937        Raises a ValueError if there is no such item.
    938
    939        Example
    940        -------
    941        ```py
    942        vec = Vec((1, 2, 3))
    943        assert vec.index(2) == 1
    944        ```
    945        """
    946        if self._ptr is None:
    947            raise ValueError from None
    948
    949        return self._ptr.index(item, start, end)

Return zero-based index in the vec of the first item whose value is equal to `item`. Raises a ValueError if there is no such item.

###### Example

    vec = Vec((1, 2, 3))
    assert vec.index(2) == 1

def count(self, item: ~T) -> int: View Source

    951    def count(self, item: T) -> int:
    952        """Return the number of occurrences of `item` in the vec.
    953
    954        `0` is returned if the vector is empty or hasn't been initialized, as well if them item not found.
    955
    956        Example
    957        --------
    958        ```py
    959        vec = Vec((1, 2, 3, 3))
    960        assert vec.count(3) == 2
    961        ```
    962        """
    963        if self._ptr is None:
    964            return 0
    965
    966        return self._ptr.count(item)

Return the number of occurrences of `item` in the vec.

`0` is returned if the vector is empty or hasn't been initialized, as well if them item not found.

###### Example

    vec = Vec((1, 2, 3, 3))
    assert vec.count(3) == 2

##### Inherited Members

sain.collections.slice.SpecContains
  contains