trait_utils/
lib.rs

1/*
2 * Description: Traits for shared behavior.
3 *
4 * Copyright (C) 2025 d@nny mc² <dmc2@hypnicjerk.ai>
5 * SPDX-License-Identifier: LGPL-3.0-or-later
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 */
20
21//! Traits for shared behavior.
22
23/* Ensure any doctest warnings fail the doctest! */
24#![doc(test(attr(deny(warnings))))]
25#![warn(missing_docs)]
26
27use std::iter;
28
29
30/// A trait for mutable growable vectors.
31pub trait VecLike: IntoIterator<Item=Self::T>+iter::Extend<Self::T> {
32  /// The type of input elements.
33  type T;
34  /// Create an instance of this container without allocating any memory.
35  ///
36  /// Also see [`ConstDefault`] for an orthogonal trait for `const` instances.
37  #[inline(always)]
38  fn new() -> Self
39  where Self: Sized {
40    Self::with_capacity(0)
41  }
42  /// Create an instance of this container with at least `n` elements allocated.
43  fn with_capacity(n: usize) -> Self
44  where Self: Sized;
45
46  /// Convert an instance of this vector into another type.
47  #[inline]
48  fn map_elements<T2, E2>(self, f: impl FnMut(Self::T) -> T2) -> E2
49  where
50    E2: VecLike<T=T2>,
51    Self: Sized,
52  {
53    let mut new_elements = E2::with_capacity(self.len());
54    new_elements.extend(self.into_iter().map(f));
55    new_elements
56  }
57
58  /// Push an element to the end.
59  fn push(&mut self, x: Self::T);
60  /// Pop an element from the end.
61  fn pop(&mut self) -> Option<Self::T>;
62  /// The number of elements.
63  fn len(&self) -> usize;
64  /// Whether there are any elements.
65  #[inline(always)]
66  fn is_empty(&self) -> bool { self.len() == 0 }
67  /// A contiguous slice of memory referring to the elements.
68  fn as_slice(&self) -> &[Self::T];
69}
70
71impl<T> VecLike for Vec<T> {
72  type T = T;
73  #[inline(always)]
74  fn new() -> Self { Vec::new() }
75  #[inline(always)]
76  fn with_capacity(n: usize) -> Self { Vec::with_capacity(n) }
77  #[inline(always)]
78  fn push(&mut self, x: T) { Vec::push(self, x); }
79  #[inline(always)]
80  fn pop(&mut self) -> Option<T> { Vec::pop(self) }
81  #[inline(always)]
82  fn len(&self) -> usize { Vec::len(self) }
83  #[inline(always)]
84  fn is_empty(&self) -> bool { Vec::is_empty(self) }
85  #[inline(always)]
86  fn as_slice(&self) -> &[Self::T] { &self[..] }
87}
88
89#[cfg(feature = "smallvec")]
90impl<T, const N: usize> VecLike for SmallVec<T, N> {
91  type T = T;
92  #[inline(always)]
93  fn new() -> Self { SmallVec::new() }
94  #[inline(always)]
95  fn with_capacity(n: usize) -> Self { SmallVec::with_capacity(n) }
96  #[inline(always)]
97  fn push(&mut self, x: T) { SmallVec::push(self, x); }
98  #[inline(always)]
99  fn pop(&mut self) -> Option<T> { SmallVec::pop(self) }
100  #[inline(always)]
101  fn len(&self) -> usize { SmallVec::len(self) }
102  #[inline(always)]
103  fn is_empty(&self) -> bool { SmallVec::is_empty(self) }
104  #[inline(always)]
105  fn as_slice(&self) -> &[Self::T] { &self[..] }
106}
107
108/// A `const` version of the [`Default`] trait.
109pub trait ConstDefault {
110  /// The statically-sized `const` instance of this type.
111  const DEFAULT: Self;
112}
113impl<T> ConstDefault for Vec<T> {
114  const DEFAULT: Self = Vec::new();
115}
116#[cfg(feature = "smallvec")]
117impl<T, const N: usize> ConstDefault for SmallVec<T, N> {
118  const DEFAULT: Self = SmallVec::new();
119}