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}