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}