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
   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]):
  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)
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]:
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]:
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]:
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:
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:
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]:
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:
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]:
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]:
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]]]':
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]]]':
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]]:
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):
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):
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]':
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]':
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:
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:
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:
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:
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:
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]':
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:
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:
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:
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:
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]':
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:
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]':
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]':
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:
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:
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:
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:
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]:
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:
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:
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:
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:
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