len_trait/
capacity.rs

1//! Traits involving the capacity of a collection.
2use super::len::Len;
3
4/// A trait for describing the capacity of a collection.
5///
6/// Because frequently allocating memory can be inefficient, collections often store room for more
7/// data than they actually hold. This "extra length" is represented by capacity, stating the
8/// maximum length that can be occupied without any memory allocations.
9///
10/// Obtaining the capacity of the collection must take a constant amount of time and space.
11pub trait Capacity: Len {
12    /// Returns the capacity of the collection.
13    ///
14    /// If this collection stores zero-sized types, then it effectively has infinite capacity. For
15    /// this reason, those collections should have a capacity of `usize::MAX`.
16    ///
17    /// # Examples
18    ///
19    /// ```rust
20    /// use len_trait::Capacity;
21    ///
22    /// fn check_capacity<C: Capacity>(collection: C, zero_sized: bool) {
23    ///     if zero_sized {
24    ///         assert_eq!(collection.capacity(), usize::max_value());
25    ///     } else {
26    ///         assert!(collection.capacity() >= collection.len());
27    ///     }
28    /// }
29    ///
30    /// check_capacity(vec![()], true);
31    /// check_capacity(vec![1, 2, 3], false);
32    /// check_capacity("Hello, world!".to_string(), false);
33    /// ```
34    fn capacity(&self) -> usize;
35}
36
37/// A trait for creating an empty collection with a given, pre-allocated capacity.
38///
39/// If a user knows in advance a minimum bound for how much capacity they will need, they can use
40/// the `with_capacity` trait to pre-allocate memory in advance. The resulting collection is
41/// guaranteed to have at least the capacity given.
42///
43/// If the given capacity is zero, then no capacity should be allocated at all. The behaviour of the
44/// `Default` implementation should act the same as `with_capacity(0)`.
45///
46/// Creating a collection with a given capacity should take linear time and space with respect to
47/// the requested capacity. Creating a collection of zero-size types should always take constant
48/// time and space.
49pub trait WithCapacity: Capacity + Default {
50    /// Creates a value of the given capacity.
51    ///
52    /// If a value of zero is given, this should have the same effect as calling `Default::default`,
53    /// and should not allocate any memory.
54    ///
55    /// # Examples
56    ///
57    /// ```rust
58    /// use len_trait::WithCapacity;
59    ///
60    /// fn check_capacity<C: WithCapacity>(zero_sized: bool) {
61    ///     let default = C::default();
62    ///     let with_cap = C::with_capacity(10);
63    ///     if zero_sized {
64    ///         assert_eq!(default.capacity(), usize::max_value());
65    ///         assert_eq!(with_cap.capacity(), usize::max_value());
66    ///     } else {
67    ///         assert_eq!(default.capacity(), 0);
68    ///         assert!(with_cap.capacity() >= 10);
69    ///     }
70    /// }
71    ///
72    /// check_capacity::<Vec<()>>(true);
73    /// check_capacity::<Vec<usize>>(false);
74    /// check_capacity::<String>(false);
75    /// ```
76    fn with_capacity(capacity: usize) -> Self;
77}
78
79/// A trait for modifying the capacity of a collection.
80///
81/// These methods are mostly hints to
82///
83/// Clearing a collection must take at most a linear amount of time and space with respect to the
84/// number of elements which are dropped.
85pub trait CapacityMut: WithCapacity {
86    /// Ensures that the capacity is at least the current length plus `additional`.
87    ///
88    /// Usually, this is used to avoid multiple allocations when you know exactly how much capacity
89    /// is needed to store data.
90    ///
91    /// # Examples
92    ///
93    /// ```rust
94    /// use len_trait::CapacityMut;
95    ///
96    /// fn check_capacity<C: CapacityMut>(mut collection: C) {
97    ///     collection.reserve(100);
98    ///     assert!(collection.capacity() >= collection.len() + 100)
99    /// }
100    ///
101    /// check_capacity(vec![1, 2, 3]);
102    /// check_capacity("Hello, world!".to_string());
103    /// ```
104    fn reserve(&mut self, additional: usize);
105
106    /// Similar to `reserve`, adding a strong hint to not reserve capacity above what's needed.
107    ///
108    /// By default, this method just delegates to `reserve` unless the implementation has a more
109    /// efficient version.
110    ///
111    /// # Examples
112    ///
113    /// ```rust
114    /// use std::collections::HashMap;
115    /// use len_trait::CapacityMut;
116    ///
117    /// fn check_capacity<C: CapacityMut>(mut collection: C, exact: bool) {
118    ///     collection.reserve_exact(100);
119    ///     if exact {
120    ///         assert_eq!(collection.capacity(), collection.len() + 100)
121    ///     } else {
122    ///         assert!(collection.capacity() > collection.len() + 100)
123    ///     }
124    /// }
125    ///
126    /// check_capacity(vec![1, 2, 3], true);
127    /// check_capacity("Hello, world!".to_string(), true);
128    /// check_capacity(
129    ///     {
130    ///         let mut map = HashMap::new();
131    ///         map.insert('a', 1);
132    ///         map.insert('b', 2);
133    ///         map.insert('c', 3);
134    ///         map
135    ///     },
136    ///     false,
137    /// );
138    /// ```
139    fn reserve_exact(&mut self, additional: usize) {
140        CapacityMut::reserve(self, additional)
141    }
142
143    /// Reduces the capacity down as close as possible to the current length.
144    ///
145    /// If the length of the collection is zero, this method will set its capacity to zero. By
146    /// default, this method does nothing unless the capacity is zero.
147    ///
148    /// # Examples
149    ///
150    /// ```rust
151    /// use len_trait::{Capacity, WithCapacity, CapacityMut};
152    ///
153    /// let mut v: Vec<usize> = WithCapacity::with_capacity(10);
154    ///
155    /// v.extend(&[1, 2, 3, 4, 5, 6][..]);
156    /// assert_eq!(v.capacity(), 10);
157    ///
158    /// CapacityMut::shrink_to_fit(&mut v);
159    /// assert_eq!(v.capacity(), 6);
160    ///
161    /// v.clear();
162    /// CapacityMut::shrink_to_fit(&mut v);
163    /// assert_eq!(v.capacity(), 0);
164    /// ```
165    fn shrink_to_fit(&mut self) {
166        if Len::is_empty(self) {
167            *self = Default::default();
168        }
169    }
170}