toad_common/
writable.rs

1use core::fmt::Display;
2use core::ops::{Deref, DerefMut};
3
4use crate::Array;
5
6/// Newtype wrapper that adds a blanket implementation of [`core::fmt::Write`]
7/// to any & all [`Array`]s
8///
9/// This allows alloc-less format strings:
10/// ```
11/// use core::fmt::Write;
12///
13/// use toad_common::{Array, Writable};
14///
15/// let mut stringish = Writable::from(vec![]);
16///
17/// write!(stringish, "Your number is: {}", 123).ok();
18/// assert_eq!(stringish.as_str(), "Your number is: 123");
19/// ```
20#[derive(Clone, Copy, Debug, Default)]
21pub struct Writable<A: Array<Item = u8>>(A);
22
23impl<A: Array<Item = u8>> Writable<A> {
24  /// Attempt to read the data in the buffer
25  /// as a UTF8 string slice
26  pub fn as_str(&self) -> &str {
27    core::str::from_utf8(self).unwrap()
28  }
29
30  /// Get a slice of the byte buffer
31  pub fn as_slice(&self) -> &[u8] {
32    &self.0
33  }
34
35  /// Get a mutable slice of the byte buffer
36  pub fn as_mut_slice(&mut self) -> &mut [u8] {
37    &mut self.0
38  }
39
40  /// Get the collection wrapped by this `Writable`
41  pub fn unwrap(self) -> A {
42    self.0
43  }
44}
45
46impl<A> Display for Writable<A> where A: Array<Item = u8>
47{
48  fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49    write!(f, "{}", self.as_str())
50  }
51}
52
53impl<A: Array<Item = u8>> From<A> for Writable<A> {
54  fn from(a: A) -> Self {
55    Self(a)
56  }
57}
58
59impl<A: Array<Item = u8>> Deref for Writable<A> {
60  type Target = A;
61
62  fn deref(&self) -> &A {
63    &self.0
64  }
65}
66
67impl<A: Array<Item = u8>> DerefMut for Writable<A> {
68  fn deref_mut(&mut self) -> &mut A {
69    &mut self.0
70  }
71}
72
73impl<A: Array<Item = u8>> AsRef<str> for Writable<A> {
74  fn as_ref(&self) -> &str {
75    self.as_str()
76  }
77}
78
79impl<A: Array<Item = u8>> core::fmt::Write for Writable<A> {
80  fn write_str(&mut self, s: &str) -> core::fmt::Result {
81    match A::CAPACITY {
82      | Some(max) if max < self.len() + s.len() => Err(core::fmt::Error),
83      | _ => {
84        self.extend(s.bytes());
85        Ok(())
86      },
87    }
88  }
89}