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> {}