1use crate::{numeric, ToStr};
2
3use core::{fmt, mem};
4
5pub struct Buffer<const N: usize> {
9 inner: [core::mem::MaybeUninit<u8>; N],
10 offset: u8,
11}
12
13impl<const N: usize> Buffer<N> {
14 #[inline]
15 pub const fn new() -> Self {
17 Self {
18 #[cfg(debug_assertions)]
19 inner: [mem::MaybeUninit::zeroed(); N],
20 #[cfg(not(debug_assertions))]
21 inner: [mem::MaybeUninit::uninit(); N],
22 offset: 0,
23 }
24 }
25
26 #[inline]
27 pub const fn as_ptr(&self) -> *const u8 {
29 self.inner.as_ptr() as _
30 }
31
32 #[inline]
33 const fn as_mut_ptr(&mut self) -> *mut u8 {
35 self.inner.as_mut_ptr() as _
36 }
37
38 #[inline]
39 pub const fn capacity() -> usize {
41 N
42 }
43
44 #[inline(always)]
45 const fn as_offset_str(&self, offset: isize) -> &str {
46 unsafe {
47 let slice = core::slice::from_raw_parts(self.as_ptr().offset(offset), Self::capacity() - offset as usize);
48 core::str::from_utf8_unchecked(slice)
49 }
50 }
51
52 #[inline(always)]
53 pub const fn as_str(&self) -> &str {
57 self.as_offset_str(self.offset as _)
58 }
59
60 #[inline]
61 pub fn write<T: ToStr>(&mut self, val: T) -> &str {
66 self.offset = (Self::capacity() - self.format(val).len()) as u8;
67 self.as_str()
68 }
69
70 #[inline(always)]
71 pub fn format<T: ToStr>(&mut self, val: T) -> &str {
75 debug_assert!(Self::capacity() <= u8::max_value() as usize);
78 debug_assert!(T::TEXT_SIZE <= Self::capacity());
79
80 val.to_str(unsafe {
81 &mut *core::ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), Self::capacity())
82 })
83 }
84 #[inline(always)]
85 pub fn fmt<T: crate::ToStr>(val: T) -> Self {
87 let mut this = Self::new();
88 this.write(val);
89 this
90 }
91}
92
93impl<const N: usize> Buffer<N> {
94 #[inline(always)]
95 pub const fn format_u8(&mut self, val: u8) -> &str {
97 assert!(Self::capacity() >= <u8 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
98
99 numeric::unsigned::u8(val, &mut self.inner)
100 }
101
102 #[inline(always)]
103 pub const fn fmt_u8(val: u8) -> Self {
105 assert!(Self::capacity() >= <u8 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
106
107 let mut this = Self::new();
108 this.offset = (Self::capacity() - numeric::unsigned::u8(val, &mut this.inner).len()) as u8;
109 this
110 }
111
112 #[inline(always)]
113 pub const fn format_u16(&mut self, val: u16) -> &str {
115 assert!(Self::capacity() >= <u16 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
116
117 numeric::unsigned::u16(val, &mut self.inner)
118 }
119
120 #[inline(always)]
121 pub const fn fmt_u16(val: u16) -> Self {
123 assert!(Self::capacity() >= <u16 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
124
125 let mut this = Self::new();
126 this.offset = (Self::capacity() - numeric::unsigned::u16(val, &mut this.inner).len()) as u8;
127 this
128 }
129
130 #[inline(always)]
131 pub const fn format_u32(&mut self, val: u32) -> &str {
133 assert!(Self::capacity() >= <u32 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
134
135 numeric::unsigned::u32(val, &mut self.inner)
136 }
137
138 #[inline(always)]
139 pub const fn fmt_u32(val: u32) -> Self {
141 assert!(Self::capacity() >= <u32 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
142
143 let mut this = Self::new();
144 this.offset = (Self::capacity() - numeric::unsigned::u32(val, &mut this.inner).len()) as u8;
145 this
146 }
147
148 #[inline(always)]
149 pub const fn format_u64(&mut self, val: u64) -> &str {
151 assert!(Self::capacity() >= <u64 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
152
153 numeric::unsigned::u64(val, &mut self.inner)
154 }
155
156 #[inline(always)]
157 pub const fn fmt_u64(val: u64) -> Self {
159 assert!(Self::capacity() >= <u64 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
160
161 let mut this = Self::new();
162 this.offset = (Self::capacity() - numeric::unsigned::u64(val, &mut this.inner).len()) as u8;
163 this
164 }
165
166 #[inline(always)]
167 pub const fn format_usize(&mut self, val: usize) -> &str {
169 assert!(Self::capacity() >= <usize as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
170
171 numeric::unsigned::usize(val, &mut self.inner)
172 }
173
174 #[inline(always)]
175 pub const fn fmt_usize(val: usize) -> Self {
177 assert!(Self::capacity() >= <usize as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
178
179 let mut this = Self::new();
180 this.offset = (Self::capacity() - numeric::unsigned::usize(val, &mut this.inner).len()) as u8;
181 this
182 }
183
184 #[inline(always)]
185 pub const fn format_u128(&mut self, val: u128) -> &str {
187 assert!(Self::capacity() >= <u128 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
188
189 numeric::unsigned::u128(val, &mut self.inner)
190 }
191
192 #[inline(always)]
193 pub const fn fmt_u128(val: u128) -> Self {
195 assert!(Self::capacity() >= <u128 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
196
197 let mut this = Self::new();
198 this.offset = (Self::capacity() - numeric::unsigned::u128(val, &mut this.inner).len()) as u8;
199 this
200 }
201}
202
203impl<const N: usize> Buffer<N> {
204 #[inline(always)]
205 pub const fn format_i8(&mut self, val: i8) -> &str {
207 assert!(Self::capacity() >= <u8 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
208
209 numeric::signed::i8(val, &mut self.inner)
210 }
211
212 #[inline(always)]
213 pub const fn fmt_i8(val: i8) -> Self {
215 assert!(Self::capacity() >= <u8 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
216
217 let mut this = Self::new();
218 this.offset = (Self::capacity() - numeric::signed::i8(val, &mut this.inner).len()) as u8;
219 this
220 }
221
222 #[inline(always)]
223 pub const fn format_i16(&mut self, val: i16) -> &str {
225 assert!(Self::capacity() >= <i16 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
226
227 numeric::signed::i16(val, &mut self.inner)
228 }
229
230 #[inline(always)]
231 pub const fn fmt_i16(val: i16) -> Self {
233 assert!(Self::capacity() >= <u16 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
234
235 let mut this = Self::new();
236 this.offset = (Self::capacity() - numeric::signed::i16(val, &mut this.inner).len()) as u8;
237 this
238 }
239
240 #[inline(always)]
241 pub const fn format_i32(&mut self, val: i32) -> &str {
243 assert!(Self::capacity() >= <i32 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
244
245 numeric::signed::i32(val, &mut self.inner)
246 }
247
248 #[inline(always)]
249 pub const fn fmt_i32(val: i32) -> Self {
251 assert!(Self::capacity() >= <i32 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
252
253 let mut this = Self::new();
254 this.offset = (Self::capacity() - numeric::signed::i32(val, &mut this.inner).len()) as u8;
255 this
256 }
257
258 #[inline(always)]
259 pub const fn format_i64(&mut self, val: i64) -> &str {
261 assert!(Self::capacity() >= <i64 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
262
263 numeric::signed::i64(val, &mut self.inner)
264 }
265
266 #[inline(always)]
267 pub const fn fmt_i64(val: i64) -> Self {
269 assert!(Self::capacity() >= <i64 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
270
271 let mut this = Self::new();
272 this.offset = (Self::capacity() - numeric::signed::i64(val, &mut this.inner).len()) as u8;
273 this
274 }
275
276 #[inline(always)]
277 pub const fn format_isize(&mut self, val: isize) -> &str {
279 assert!(Self::capacity() >= <isize as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
280
281 numeric::signed::isize(val, &mut self.inner)
282 }
283
284 #[inline(always)]
285 pub const fn fmt_isize(val: isize) -> Self {
287 assert!(Self::capacity() >= <isize as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
288
289 let mut this = Self::new();
290 this.offset = (Self::capacity() - numeric::signed::isize(val, &mut this.inner).len()) as u8;
291 this
292 }
293
294 #[inline(always)]
295 pub const fn format_i128(&mut self, val: i128) -> &str {
297 assert!(Self::capacity() >= <i128 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
298
299 numeric::signed::i128(val, &mut self.inner)
300 }
301
302 #[inline(always)]
303 pub const fn fmt_i128(val: i128) -> Self {
305 assert!(Self::capacity() >= <i128 as ToStr>::TEXT_SIZE, "Capacity should be sufficient");
306
307 let mut this = Self::new();
308 this.offset = (Self::capacity() - numeric::signed::i128(val, &mut this.inner).len()) as u8;
309 this
310 }
311}
312
313impl<const N: usize> AsRef<str> for Buffer<N> {
314 #[inline(always)]
315 fn as_ref(&self) -> &str {
316 self.as_str()
317 }
318}
319
320impl<const N: usize> fmt::Display for Buffer<N> {
321 #[inline(always)]
322 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
323 fmt.write_str(self.as_str())
324 }
325}
326
327impl<const N: usize> fmt::Debug for Buffer<N> {
328 #[inline(always)]
329 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
330 fmt::Debug::fmt(self.as_str(), fmt)
331 }
332}