len_trait/len.rs
1//! Traits involving the length of a collection.
2
3/// A trait for describing whether a collection is empty, i.e., its length is zero.
4///
5/// Checking whether a collection is empty should take a constant amount of time and space.
6pub trait Empty {
7 /// Returns whether the collection is empty.
8 ///
9 /// # Examples
10 ///
11 /// ```rust
12 /// use len_trait::Empty;
13 ///
14 /// fn check_empty<C: ?Sized + Empty>(collection: &C) {
15 /// assert!(collection.is_empty());
16 /// }
17 ///
18 /// check_empty("");
19 /// check_empty(&[1, 2, 3][..0]);
20 /// check_empty(&"".to_string());
21 /// ```
22 fn is_empty(&self) -> bool;
23}
24
25
26/// A trait for describing the length of a collection.
27///
28/// The amount of data stored in a collection, i.e. the amount of space it requires in memory, is
29/// directly proportional to its length. For this reason, `str` and other types measure their
30/// lengths in code values (e.g. `u8`), not code points (e.g. `char`).
31///
32/// Obtaining the length of the collection must take a constant amount of time and space.
33#[cfg_attr(feature = "cargo-clippy", allow(len_without_is_empty))]
34// TODO: https://github.com/Manishearth/rust-clippy/issues/1740
35pub trait Len: Empty {
36 /// Returns the length of the collection.
37 ///
38 /// # Examples
39 ///
40 /// ```rust
41 /// use len_trait::Len;
42 ///
43 /// fn print_len<C: ?Sized + Len>(collection: &C) {
44 /// println!("{} units long", collection.len());
45 /// }
46 ///
47 /// print_len("中文"); // 6 units long
48 /// print_len(&[1, 2, 3][..]); // 3 units long
49 /// ```
50 fn len(&self) -> usize;
51}
52
53/// A trait for clearing collections.
54///
55/// A collection is cleared by dropping all of its data. After `clear` is called, the collection is
56/// guaranteed to be empty.
57///
58/// Clearing a collection must take at most a linear amount of time and space.
59pub trait Clear: Len {
60 /// Clears the collection, dropping its elements and returning its length to zero.
61 ///
62 /// # Examples
63 ///
64 /// ```rust
65 /// use len_trait::Clear;
66 ///
67 /// struct Value(u32);
68 /// impl Drop for Value {
69 /// fn drop(&mut self) {
70 /// println!("Dropped a {}", self.0)
71 /// }
72 /// }
73 ///
74 /// fn check_clear<C: Clear>(mut collection: C) {
75 /// collection.clear();
76 /// assert!(collection.is_empty());
77 /// }
78 ///
79 /// check_clear(vec![Value(12)]); // Prints "Dropped a 12"
80 /// check_clear("Hello, world!".to_string());
81 /// ```
82 fn clear(&mut self);
83}
84
85/// A trait for modifying the length of a collection.
86///
87/// These methods must take at most a linear amount of time and space with respect to the number of
88/// elements which are moved or dropped.
89pub trait LenMut: Default + Clear {
90 /// Truncates the collection to be no greater than `len` long, dropping elements as needed.
91 ///
92 /// If the collection is less than `len` long, do nothing.
93 ///
94 /// # Panics
95 ///
96 /// Panics if `len` is not valid according to the collection. For example, the implementation
97 /// for `String` will panic if `len` does not lie on a character boundary.
98 ///
99 /// # Examples
100 ///
101 /// ```rust
102 /// use len_trait::LenMut;
103 ///
104 /// fn check_truncate<C: LenMut>(mut collection: C) {
105 /// let old_len = collection.len();
106 /// collection.truncate(5);
107 /// if old_len >= 5 {
108 /// assert_eq!(collection.len(), 5);
109 /// } else {
110 /// assert_eq!(collection.len(), old_len);
111 /// }
112 /// }
113 ///
114 /// check_truncate("Hello, world!".to_string());
115 /// check_truncate(vec![1, 2, 3]);
116 /// ```
117 fn truncate(&mut self, len: usize);
118
119 /// Splits off the collection at the given index, returning the data past the index.
120 ///
121 /// # Panics
122 ///
123 /// Panics if `index > len`.
124 ///
125 /// # Examples
126 ///
127 /// ```rust
128 /// use len_trait::LenMut;
129 ///
130 /// fn check_split_off<C: LenMut>(mut collection: C) {
131 /// let old_len = collection.len();
132 /// let split = collection.split_off(5);
133 /// assert_eq!(collection.len(), 5);
134 /// assert_eq!(split.len(), old_len - 5);
135 /// }
136 ///
137 /// check_split_off("Hello, world!".to_string());
138 /// check_split_off(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
139 /// ```
140 fn split_off(&mut self, index: usize) -> Self;
141}