to_str/
buffer.rs

1use core::mem;
2
3///Static buffer to hold written text.
4///
5///Implementation of `ToStr` must write it from the end.
6pub struct Buffer<T> {
7    inner: core::mem::MaybeUninit<T>,
8    offset: u8,
9}
10
11impl<S: Sized> Buffer<S> {
12    #[inline]
13    ///Creates new instance
14    pub const fn new() -> Self {
15        Self {
16            inner: core::mem::MaybeUninit::uninit(),
17            offset: 0,
18        }
19    }
20
21    #[inline]
22    ///Returns pointer  to the beginning of underlying buffer
23    pub const fn as_ptr(&self) -> *const u8 {
24        &self.inner as *const _ as *const u8
25    }
26
27    #[inline]
28    ///Returns buffer overall capacity.
29    pub const fn capacity() -> usize {
30        mem::size_of::<S>()
31    }
32
33    #[inline(always)]
34    ///Access str from underlying storage
35    ///
36    ///Returns empty if nothing has been written into buffer yet.
37    pub fn as_str(&self) -> &str {
38        unsafe {
39            let slice = core::slice::from_raw_parts(self.as_ptr().offset(self.offset as isize), Self::capacity() - self.offset as usize);
40            core::str::from_utf8_unchecked(slice)
41        }
42    }
43
44    #[inline]
45    ///Formats value into buffer, returning text.
46    ///
47    ///Buffer remembers the write, therefore `as_str()` will return the same text as last
48    ///`write`
49    pub fn write<T: crate::ToStr>(&mut self, val: T) -> &str {
50        self.offset = (Self::capacity() - self.format(val).len()) as u8;
51        self.as_str()
52    }
53
54    #[inline(always)]
55    ///Formats value into buffer, returning text.
56    ///
57    ///Buffer remains unaware of modifications
58    pub fn format<T: crate::ToStr>(&mut self, val: T) -> &str {
59        //Yes, because we cannot assert statically in generics, we must go through these hacks
60        //We can add this assertion once panic will be allowed inside const fn
61        debug_assert!(Self::capacity() <= u8::max_value() as usize);
62        debug_assert!(T::TEXT_SIZE <= Self::capacity());
63
64        val.to_str(unsafe {
65            &mut *core::ptr::slice_from_raw_parts_mut(self.as_ptr() as *mut u8, Self::capacity())
66        })
67    }
68
69    #[inline(always)]
70    ///Creates new instance with formatted value.
71    pub fn fmt<T: crate::ToStr>(val: T) -> Self {
72        let mut this = Self::new();
73        this.write(val);
74        this
75    }
76}
77
78impl<S: Sized> AsRef<str> for Buffer<S> {
79    #[inline(always)]
80    fn as_ref(&self) -> &str {
81        self.as_str()
82    }
83}
84
85impl<S: Sized> core::fmt::Display for Buffer<S> {
86    #[inline(always)]
87    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
88        f.write_str(self.as_str())
89    }
90}
91
92impl<S: Sized> core::fmt::Debug for Buffer<S> {
93    #[inline(always)]
94    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
95        f.write_str(self.as_str())
96    }
97}