1use crate::{numeric, ToStr};
2use crate::utils::AssertSizeIsLessOrEqualThan;
3
4use core::{fmt, mem};
5
6pub struct Buffer<const N: usize> {
28 inner: [core::mem::MaybeUninit<u8>; N],
29 offset: u8,
30}
31
32impl<const N: usize> Buffer<N> {
33 const VALIDATION: () = {
34 assert!(Self::capacity() <= u8::MAX as usize, "Buffer capacity cannot be greater than 255");
35 };
36
37 #[inline]
38 pub const fn new() -> Self {
40 let _ = Self::VALIDATION;
41 Self {
42 #[cfg(debug_assertions)]
43 inner: [mem::MaybeUninit::zeroed(); N],
44 #[cfg(not(debug_assertions))]
45 inner: [mem::MaybeUninit::uninit(); N],
46 offset: 0,
47 }
48 }
49
50 #[inline]
51 pub const fn as_ptr(&self) -> *const u8 {
53 self.inner.as_ptr() as _
54 }
55
56 #[inline]
57 const fn as_mut_ptr(&mut self) -> *mut u8 {
59 self.inner.as_mut_ptr() as _
60 }
61
62 #[inline]
63 pub const fn capacity() -> usize {
65 N
66 }
67
68 #[inline(always)]
69 const fn as_offset_str(&self, offset: isize) -> &str {
70 unsafe {
71 let slice = core::slice::from_raw_parts(self.as_ptr().offset(offset), Self::capacity() - offset as usize);
72 core::str::from_utf8_unchecked(slice)
73 }
74 }
75
76 #[inline(always)]
77 pub const fn as_str(&self) -> &str {
81 self.as_offset_str(self.offset as _)
82 }
83
84 #[inline]
85 pub fn write<T: ToStr>(&mut self, val: T) -> &str {
90 self.offset = (Self::capacity() - self.format(val).len()) as u8;
91 self.as_str()
92 }
93
94 #[inline(always)]
95 pub fn format<T: ToStr>(&mut self, val: T) -> &str {
99 let _ = Self::VALIDATION;
100 assert!(T::TEXT_SIZE <= Self::capacity());
101
102 val.to_str(unsafe {
103 &mut *core::ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), Self::capacity())
104 })
105 }
106 #[inline(always)]
107 pub fn fmt<T: crate::ToStr>(val: T) -> Self {
109 let mut this = Self::new();
110 this.write(val);
111 this
112 }
113}
114
115impl<const N: usize> Buffer<N> {
116 #[inline(always)]
117 pub const fn format_u8(&mut self, val: u8) -> &str {
119 let _ = AssertSizeIsLessOrEqualThan::<{<u8 as ToStr>::TEXT_SIZE}, N>::RESULT;
120
121 numeric::unsigned::u8(val, &mut self.inner)
122 }
123
124 #[inline(always)]
125 pub const fn fmt_u8(val: u8) -> Self {
127 let _ = AssertSizeIsLessOrEqualThan::<{<u8 as ToStr>::TEXT_SIZE}, N>::RESULT;
128
129 let mut this = Self::new();
130 this.offset = (Self::capacity() - numeric::unsigned::u8(val, &mut this.inner).len()) as u8;
131 this
132 }
133
134 #[inline(always)]
135 pub const fn format_u16(&mut self, val: u16) -> &str {
137 let _ = AssertSizeIsLessOrEqualThan::<{<u16 as ToStr>::TEXT_SIZE}, N>::RESULT;
138
139 numeric::unsigned::u16(val, &mut self.inner)
140 }
141
142 #[inline(always)]
143 pub const fn fmt_u16(val: u16) -> Self {
145 let _ = AssertSizeIsLessOrEqualThan::<{<u16 as ToStr>::TEXT_SIZE}, N>::RESULT;
146
147 let mut this = Self::new();
148 this.offset = (Self::capacity() - numeric::unsigned::u16(val, &mut this.inner).len()) as u8;
149 this
150 }
151
152 #[inline(always)]
153 pub const fn format_u32(&mut self, val: u32) -> &str {
155 let _ = AssertSizeIsLessOrEqualThan::<{<u32 as ToStr>::TEXT_SIZE}, N>::RESULT;
156
157 numeric::unsigned::u32(val, &mut self.inner)
158 }
159
160 #[inline(always)]
161 pub const fn fmt_u32(val: u32) -> Self {
163 let _ = AssertSizeIsLessOrEqualThan::<{<u32 as ToStr>::TEXT_SIZE}, N>::RESULT;
164
165 let mut this = Self::new();
166 this.offset = (Self::capacity() - numeric::unsigned::u32(val, &mut this.inner).len()) as u8;
167 this
168 }
169
170 #[inline(always)]
171 pub const fn format_u64(&mut self, val: u64) -> &str {
173 let _ = AssertSizeIsLessOrEqualThan::<{<u64 as ToStr>::TEXT_SIZE}, N>::RESULT;
174
175 numeric::unsigned::u64(val, &mut self.inner)
176 }
177
178 #[inline(always)]
179 pub const fn fmt_u64(val: u64) -> Self {
181 let _ = AssertSizeIsLessOrEqualThan::<{<u64 as ToStr>::TEXT_SIZE}, N>::RESULT;
182
183 let mut this = Self::new();
184 this.offset = (Self::capacity() - numeric::unsigned::u64(val, &mut this.inner).len()) as u8;
185 this
186 }
187
188 #[inline(always)]
189 pub const fn format_usize(&mut self, val: usize) -> &str {
191 let _ = AssertSizeIsLessOrEqualThan::<{<usize as ToStr>::TEXT_SIZE}, N>::RESULT;
192
193 numeric::unsigned::usize(val, &mut self.inner)
194 }
195
196 #[inline(always)]
197 pub const fn fmt_usize(val: usize) -> Self {
199 let _ = AssertSizeIsLessOrEqualThan::<{<usize as ToStr>::TEXT_SIZE}, N>::RESULT;
200
201 let mut this = Self::new();
202 this.offset = (Self::capacity() - numeric::unsigned::usize(val, &mut this.inner).len()) as u8;
203 this
204 }
205
206 #[inline(always)]
207 pub const fn format_u128(&mut self, val: u128) -> &str {
209 let _ = AssertSizeIsLessOrEqualThan::<{<u128 as ToStr>::TEXT_SIZE}, N>::RESULT;
210
211 numeric::unsigned::u128(val, &mut self.inner)
212 }
213
214 #[inline(always)]
215 pub const fn fmt_u128(val: u128) -> Self {
217 let _ = AssertSizeIsLessOrEqualThan::<{<u128 as ToStr>::TEXT_SIZE}, N>::RESULT;
218
219 let mut this = Self::new();
220 this.offset = (Self::capacity() - numeric::unsigned::u128(val, &mut this.inner).len()) as u8;
221 this
222 }
223}
224
225impl<const N: usize> Buffer<N> {
226 #[inline(always)]
227 pub const fn format_i8(&mut self, val: i8) -> &str {
229 let _ = AssertSizeIsLessOrEqualThan::<{<i8 as ToStr>::TEXT_SIZE}, N>::RESULT;
230
231 numeric::signed::i8(val, &mut self.inner)
232 }
233
234 #[inline(always)]
235 pub const fn fmt_i8(val: i8) -> Self {
237 let _ = AssertSizeIsLessOrEqualThan::<{<i8 as ToStr>::TEXT_SIZE}, N>::RESULT;
238
239 let mut this = Self::new();
240 this.offset = (Self::capacity() - numeric::signed::i8(val, &mut this.inner).len()) as u8;
241 this
242 }
243
244 #[inline(always)]
245 pub const fn format_i16(&mut self, val: i16) -> &str {
247 let _ = AssertSizeIsLessOrEqualThan::<{<i16 as ToStr>::TEXT_SIZE}, N>::RESULT;
248
249 numeric::signed::i16(val, &mut self.inner)
250 }
251
252 #[inline(always)]
253 pub const fn fmt_i16(val: i16) -> Self {
255 let _ = AssertSizeIsLessOrEqualThan::<{<i16 as ToStr>::TEXT_SIZE}, N>::RESULT;
256
257 let mut this = Self::new();
258 this.offset = (Self::capacity() - numeric::signed::i16(val, &mut this.inner).len()) as u8;
259 this
260 }
261
262 #[inline(always)]
263 pub const fn format_i32(&mut self, val: i32) -> &str {
265 let _ = AssertSizeIsLessOrEqualThan::<{<i32 as ToStr>::TEXT_SIZE}, N>::RESULT;
266
267 numeric::signed::i32(val, &mut self.inner)
268 }
269
270 #[inline(always)]
271 pub const fn fmt_i32(val: i32) -> Self {
273 let _ = AssertSizeIsLessOrEqualThan::<{<i32 as ToStr>::TEXT_SIZE}, N>::RESULT;
274
275 let mut this = Self::new();
276 this.offset = (Self::capacity() - numeric::signed::i32(val, &mut this.inner).len()) as u8;
277 this
278 }
279
280 #[inline(always)]
281 pub const fn format_i64(&mut self, val: i64) -> &str {
283 let _ = AssertSizeIsLessOrEqualThan::<{<i64 as ToStr>::TEXT_SIZE}, N>::RESULT;
284
285 numeric::signed::i64(val, &mut self.inner)
286 }
287
288 #[inline(always)]
289 pub const fn fmt_i64(val: i64) -> Self {
291 let _ = AssertSizeIsLessOrEqualThan::<{<i64 as ToStr>::TEXT_SIZE}, N>::RESULT;
292
293 let mut this = Self::new();
294 this.offset = (Self::capacity() - numeric::signed::i64(val, &mut this.inner).len()) as u8;
295 this
296 }
297
298 #[inline(always)]
299 pub const fn format_isize(&mut self, val: isize) -> &str {
301 let _ = AssertSizeIsLessOrEqualThan::<{<isize as ToStr>::TEXT_SIZE}, N>::RESULT;
302
303 numeric::signed::isize(val, &mut self.inner)
304 }
305
306 #[inline(always)]
307 pub const fn fmt_isize(val: isize) -> Self {
309 let _ = AssertSizeIsLessOrEqualThan::<{<isize as ToStr>::TEXT_SIZE}, N>::RESULT;
310
311 let mut this = Self::new();
312 this.offset = (Self::capacity() - numeric::signed::isize(val, &mut this.inner).len()) as u8;
313 this
314 }
315
316 #[inline(always)]
317 pub const fn format_i128(&mut self, val: i128) -> &str {
319 let _ = AssertSizeIsLessOrEqualThan::<{<i128 as ToStr>::TEXT_SIZE}, N>::RESULT;
320
321 numeric::signed::i128(val, &mut self.inner)
322 }
323
324 #[inline(always)]
325 pub const fn fmt_i128(val: i128) -> Self {
327 let _ = AssertSizeIsLessOrEqualThan::<{<i128 as ToStr>::TEXT_SIZE}, N>::RESULT;
328
329 let mut this = Self::new();
330 this.offset = (Self::capacity() - numeric::signed::i128(val, &mut this.inner).len()) as u8;
331 this
332 }
333}
334
335impl<const N: usize> AsRef<str> for Buffer<N> {
336 #[inline(always)]
337 fn as_ref(&self) -> &str {
338 self.as_str()
339 }
340}
341
342impl<const N: usize> fmt::Display for Buffer<N> {
343 #[inline(always)]
344 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
345 fmt.write_str(self.as_str())
346 }
347}
348
349impl<const N: usize> fmt::Debug for Buffer<N> {
350 #[inline(always)]
351 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
352 fmt::Debug::fmt(self.as_str(), fmt)
353 }
354}