kwap_common/lib.rs
1//! Common structs and abstractions used by `kwap`
2
3#![doc(html_root_url = "https://docs.rs/kwap-common/0.7.0")]
4#![cfg_attr(all(not(test), feature = "no_std"), no_std)]
5#![cfg_attr(not(test), forbid(missing_debug_implementations, unreachable_pub))]
6#![cfg_attr(not(test), deny(unsafe_code, missing_copy_implementations))]
7#![allow(clippy::unused_unit)]
8#![deny(missing_docs)]
9
10extern crate alloc;
11use alloc::vec::Vec;
12use core::ops::{Deref, DerefMut};
13
14/// Extensions to Result
15pub mod result;
16
17/// Function utils
18pub mod fns;
19
20/// Dictionary
21pub mod map;
22pub use map::*;
23
24/// `kwap` prelude
25pub mod prelude {
26  pub use fns::*;
27  pub use result::*;
28
29  pub use super::*;
30}
31
32/// An ordered indexable collection of some type `Item`
33///
34/// # Provided implementations
35/// - [`Vec`]
36/// - [`tinyvec::ArrayVec`]
37///
38/// Notably, not `heapless::ArrayVec` or `arrayvec::ArrayVec`. An important usecase within `kwap`
39/// is [`Extend`]ing the collection, and the performance of `heapless` and `arrayvec`'s Extend implementations
40/// are notably worse than `tinyvec`.
41///
42/// `tinyvec` also has the added bonus of being 100% unsafe-code-free, meaning if you choose `tinyvec` you eliminate the
43/// possibility of memory defects and UB.
44///
45/// # Requirements
46/// - [`Default`] for creating the collection
47/// - [`Extend`] for mutating and adding onto the collection (1 or more elements)
48/// - [`Reserve`] for reserving space ahead of time
49/// - [`GetSize`] for bound checks, empty checks, and accessing the length
50/// - [`FromIterator`] for [`collect`](core::iter::Iterator#method.collect)ing into the collection
51/// - [`IntoIterator`] for iterating and destroying the collection
52/// - [`Deref<Target = [T]>`](Deref) and [`DerefMut`] for:
53///    - indexing ([`Index`](core::ops::Index), [`IndexMut`](core::ops::IndexMut))
54///    - iterating ([`&[T].iter()`](primitive@slice#method.iter) and [`&mut [T].iter_mut()`](primitive@slice#method.iter_mut))
55pub trait Array:
56  Default
57  + GetSize
58  + Reserve
59  + Deref<Target = [<Self as Array>::Item]>
60  + DerefMut
61  + Extend<<Self as Array>::Item>
62  + FromIterator<<Self as Array>::Item>
63  + IntoIterator<Item = <Self as Array>::Item>
64{
65  /// The type of item contained in the collection
66  type Item;
67
68  /// Insert a value at a particular index of a collection.
69  fn insert_at(&mut self, index: usize, value: <Self as Array>::Item);
70
71  /// Try to remove an entry from the collection.
72  ///
73  /// Returns `Some(Self::Item)` if `index` was in-bounds, `None` if `index` is out of bounds.
74  fn remove(&mut self, index: usize) -> Option<<Self as Array>::Item>;
75
76  /// Add a value to the end of a collection.
77  fn push(&mut self, value: <Self as Array>::Item);
78}
79
80impl<T> Array for Vec<T> {
81  type Item = T;
82
83  fn insert_at(&mut self, index: usize, value: T) {
84    self.insert(index, value);
85  }
86
87  fn remove(&mut self, index: usize) -> Option<T> {
88    if index < self.len() {
89      Some(Vec::remove(self, index))
90    } else {
91      None
92    }
93  }
94
95  fn push(&mut self, value: T) {
96    self.push(value)
97  }
98}
99
100/// A writeable byte buffer
101///
102/// (allows using `write!` and `format!` without allocations)
103///
104/// ```
105/// use core::fmt::Write as _;
106///
107/// use kwap_common::{Array, Writable};
108///
109/// let mut faux_string = Writable::<tinyvec::ArrayVec<[u8; 16]>>::default();
110/// write!(faux_string, "{}", 123).unwrap();
111///
112/// assert_eq!(faux_string.as_str(), "123");
113/// ```
114#[derive(Clone, Copy, Debug, Default)]
115pub struct Writable<A: Array<Item = u8>>(A);
116
117impl<A: Array<Item = u8>> Writable<A> {
118  /// Convert the buffer to a string slice
119  pub fn as_str(&self) -> &str {
120    core::str::from_utf8(self).unwrap()
121  }
122}
123
124impl<A: Array<Item = u8>> Deref for Writable<A> {
125  type Target = A;
126
127  fn deref(&self) -> &A {
128    &self.0
129  }
130}
131
132impl<A: Array<Item = u8>> DerefMut for Writable<A> {
133  fn deref_mut(&mut self) -> &mut A {
134    &mut self.0
135  }
136}
137
138impl<A: Array<Item = u8>> AsRef<str> for Writable<A> {
139  fn as_ref(&self) -> &str {
140    self.as_str()
141  }
142}
143
144impl<A: Array<Item = u8>> core::fmt::Write for Writable<A> {
145  fn write_str(&mut self, s: &str) -> core::fmt::Result {
146    match self.0.max_size() {
147      | Some(max) if max < self.len() + s.len() => Err(core::fmt::Error),
148      | _ => {
149        self.extend(s.bytes());
150        Ok(())
151      },
152    }
153  }
154}
155
156impl<A: tinyvec::Array<Item = T>, T> Array for tinyvec::ArrayVec<A> {
157  type Item = T;
158
159  fn insert_at(&mut self, index: usize, value: A::Item) {
160    self.insert(index, value);
161  }
162
163  fn remove(&mut self, index: usize) -> Option<T> {
164    if index < self.len() {
165      Some(tinyvec::ArrayVec::remove(self, index))
166    } else {
167      None
168    }
169  }
170
171  fn push(&mut self, value: A::Item) {
172    self.push(value)
173  }
174}
175
176/// Get the runtime size of some data structure
177///
178/// # Deprecated
179/// Note: in a future version of `kwap_common` this will be deprecated in favor of clearly delineating
180/// "size in bytes" (e.g. `RuntimeSize`) from "collection of potentially bounded length" (e.g. `Len`)
181///
182/// ## Collections
183/// For collections this just yields the number of elements ([`Vec::len`], [`tinyvec::ArrayVec::len`]),
184/// and when the collection is over [`u8`]s,
185/// then `get_size` represents the number of bytes in the collection.
186///
187/// ## Structs and enums
188/// When implemented for items that are not collections,
189/// this is expected to yield the runtime size in bytes
190/// (not the static Rust [`core::mem::size_of`] size)
191pub trait GetSize {
192  /// Get the runtime size (in bytes) of a struct
193  ///
194  /// For collections this is always equivalent to calling an inherent `len` method.
195  ///
196  /// ```
197  /// use kwap_common::GetSize;
198  ///
199  /// assert_eq!(vec![1u8, 2].get_size(), 2)
200  /// ```
201  fn get_size(&self) -> usize;
202
203  /// Get the max size that this data structure can acommodate.
204  ///
205  /// By default, this returns `None` and can be left unimplemented for dynamic collections.
206  ///
207  /// However, for fixed-size collections this method must be implemented.
208  ///
209  /// ```
210  /// use kwap_common::GetSize;
211  ///
212  /// let stack_nums = tinyvec::ArrayVec::<[u8; 2]>::from([0, 1]);
213  /// assert_eq!(stack_nums.max_size(), Some(2));
214  /// ```
215  fn max_size(&self) -> Option<usize>;
216
217  /// Check if the runtime size is zero
218  ///
219  /// ```
220  /// use kwap_common::GetSize;
221  ///
222  /// assert!(Vec::<u8>::new().size_is_zero())
223  /// ```
224  fn size_is_zero(&self) -> bool {
225    self.get_size() == 0
226  }
227
228  /// Is there no room left in this collection?
229  ///
230  /// ```
231  /// use kwap_common::GetSize;
232  ///
233  /// let array = tinyvec::ArrayVec::<[u8; 2]>::from([1, 2]);
234  ///
235  /// assert!(array.is_full())
236  /// ```
237  fn is_full(&self) -> bool {
238    self.max_size()
239        .map(|max| self.get_size() >= max)
240        .unwrap_or(false)
241  }
242}
243
244impl<T> GetSize for Vec<T> {
245  fn get_size(&self) -> usize {
246    self.len()
247  }
248
249  fn max_size(&self) -> Option<usize> {
250    None
251  }
252}
253
254impl<A: tinyvec::Array> GetSize for tinyvec::ArrayVec<A> {
255  fn get_size(&self) -> usize {
256    self.len()
257  }
258
259  fn max_size(&self) -> Option<usize> {
260    Some(A::CAPACITY)
261  }
262}
263
264/// Create a data structure and reserve some amount of space for it to grow into
265///
266/// # Examples
267/// - `Vec` is `Reserve`, and invokes `Vec::with_capacity`
268/// - `tinyvec::ArrayVec` is `Reserve` and invokes `Default::default()` because creating an `ArrayVec` automatically allocates the required space on the stack.
269pub trait Reserve: Default {
270  /// Create an instance of the collection with a given capacity.
271  ///
272  /// Used to reserve some contiguous space, e.g. [`Vec::with_capacity`]
273  ///
274  /// The default implementation invokes `Default::default`
275  fn reserve(_: usize) -> Self {
276    Default::default()
277  }
278}
279
280impl<T> Reserve for Vec<T> {
281  fn reserve(n: usize) -> Self {
282    Self::with_capacity(n)
283  }
284}
285
286impl<A: tinyvec::Array> Reserve for tinyvec::ArrayVec<A> {}