1use core::mem::MaybeUninit;
2
3use crate::{fmt::Write, Error};
4
5const MAX_CAPACITY: usize = u16::MAX as usize;
6const MAX_INTEGER_LEN: u8 = 20;
8const MAX_PRECISION: usize = 9;
9
10const BROAD_MINIMUM_BUFFER_LEN: usize = 20;
15
16const RADIX_100_ZERO: [u8; 200] = *b"00010203040506070809\
18 10111213141516171819\
19 20212223242526272829\
20 30313233343536373839\
21 40414243444546474849\
22 50515253545556575859\
23 60616263646566676869\
24 70717273747576777879\
25 80818283848586878889\
26 90919293949596979899";
27
28const RADIX_100_SPACE: [u8; 200] = *b" 0 1 2 3 4 5 6 7 8 9\
30 10111213141516171819\
31 20212223242526272829\
32 30313233343536373839\
33 40414243444546474849\
34 50515253545556575859\
35 60616263646566676869\
36 70717273747576777879\
37 80818283848586878889\
38 90919293949596979899";
39
40#[derive(Clone, Copy)]
44pub(crate) struct ArrayBuffer<const N: usize> {
45 data: [MaybeUninit<u8>; N],
46}
47
48impl<const N: usize> ArrayBuffer<N> {
49 #[cfg_attr(feature = "perf-inline", inline(always))]
51 pub(crate) fn as_borrowed<'data>(&mut self) -> BorrowedBuffer<'_> {
52 BorrowedBuffer::from(&mut self.data)
53 }
54
55 unsafe fn assume_init(self) -> [u8; N] {
61 unsafe {
65 *(&self.data as *const [MaybeUninit<u8>; N] as *const [u8; N])
66 }
67 }
68}
69
70impl<const N: usize> Default for ArrayBuffer<N> {
72 #[cfg_attr(feature = "perf-inline", inline(always))]
73 fn default() -> ArrayBuffer<N> {
74 ArrayBuffer { data: [MaybeUninit::uninit(); N] }
75 }
76}
77
78#[derive(Debug)]
102pub(crate) struct BorrowedBuffer<'data> {
103 data: &'data mut [MaybeUninit<u8>],
104 filled: u16,
105}
106
107impl<'data> BorrowedBuffer<'data> {
108 #[cfg_attr(feature = "perf-inline", inline(always))]
115 pub(crate) fn with_writer<const N: usize>(
116 wtr: &mut dyn Write,
117 _runtime_allocation: usize,
118 mut with: impl FnMut(&mut BorrowedBuffer<'_>) -> Result<(), Error>,
119 ) -> Result<(), Error> {
120 #[cfg(feature = "alloc")]
131 if let Some(buf) = unsafe { wtr.as_mut_vec() } {
132 buf.reserve(_runtime_allocation);
133 return BorrowedBuffer::with_vec_spare_capacity(buf, with);
134 }
135 let mut buf = ArrayBuffer::<N>::default();
136 let mut bbuf = buf.as_borrowed();
137 with(&mut bbuf)?;
138 wtr.write_str(bbuf.filled())?;
139 Ok(())
140 }
141
142 #[cfg(feature = "alloc")]
154 #[cfg_attr(feature = "perf-inline", inline(always))]
155 pub(crate) fn with_vec_spare_capacity<T>(
156 buf: &'data mut alloc::vec::Vec<u8>,
157 mut with: impl FnMut(&mut BorrowedBuffer<'_>) -> T,
158 ) -> T {
159 let mut bbuf = BorrowedBuffer::from_vec_spare_capacity(buf);
160 let returned = with(&mut bbuf);
161 let new_len = bbuf.len();
162 unsafe {
166 buf.set_len(new_len);
167 }
168 returned
169 }
170
171 #[cfg(feature = "alloc")]
176 #[cfg_attr(feature = "perf-inline", inline(always))]
177 pub(crate) fn from_vec_spare_capacity(
178 vec: &'data mut alloc::vec::Vec<u8>,
179 ) -> BorrowedBuffer<'data> {
180 let data = vec.spare_capacity_mut();
181 let len = data.len().min(MAX_CAPACITY);
182 BorrowedBuffer::from(&mut data[..len])
183 }
184
185 #[cfg_attr(feature = "perf-inline", inline(always))]
192 pub(crate) fn write_str(&mut self, string: &str) {
193 let data: &[MaybeUninit<u8>] = unsafe {
196 core::slice::from_raw_parts(
197 string.as_ptr().cast::<MaybeUninit<u8>>(),
198 string.len(),
199 )
200 };
201 self.available()
202 .get_mut(..string.len())
203 .expect("string data exceeds available buffer space")
204 .copy_from_slice(data);
205 self.filled += string.len() as u16;
211 }
212
213 #[cfg_attr(feature = "perf-inline", inline(always))]
220 pub(crate) fn write_char(&mut self, ch: char) {
221 self.write_str(ch.encode_utf8(&mut [0; 4]));
222 }
223
224 #[cfg_attr(feature = "perf-inline", inline(always))]
230 pub(crate) fn write_ascii_char(&mut self, byte: u8) {
231 assert!(byte.is_ascii());
232 self.available()
233 .get_mut(0)
234 .expect("insufficient buffer space to write one byte")
235 .write(byte);
236 self.filled += 1;
237 }
238
239 #[cfg_attr(feature = "perf-inline", inline(always))]
246 pub(crate) fn write_int(&mut self, n: impl Into<u64>) {
247 let mut n = n.into();
248 let digits = digits(n);
249 let mut remaining_digits = usize::from(digits);
250 let available = self
251 .available()
252 .get_mut(..remaining_digits)
253 .expect("u8 integer digits exceeds available buffer space");
254 while remaining_digits > 0 {
255 remaining_digits -= 1;
256 unsafe {
259 available
260 .get_unchecked_mut(remaining_digits)
261 .write(b'0' + ((n % 10) as u8));
262 }
263 n /= 10;
264 }
265 self.filled += u16::from(digits);
266 }
267
268 #[cfg_attr(feature = "perf-inline", inline(always))]
282 pub(crate) fn write_int_pad0(&mut self, n: impl Into<u64>, pad_len: u8) {
283 let mut n = n.into();
284 let pad_len = pad_len.min(MAX_INTEGER_LEN);
285 let digits = pad_len.max(digits(n));
286 let mut remaining_digits = usize::from(digits);
287 let available = self
288 .available()
289 .get_mut(..remaining_digits)
290 .expect("u8 integer digits exceeds available buffer space");
291 while remaining_digits > 0 {
292 remaining_digits -= 1;
293 unsafe {
296 available
297 .get_unchecked_mut(remaining_digits)
298 .write(b'0' + ((n % 10) as u8));
299 }
300 n /= 10;
301 }
302 self.filled += u16::from(digits);
303 }
304
305 #[cfg_attr(feature = "perf-inline", inline(always))]
317 pub(crate) fn write_int_pad(
318 &mut self,
319 n: impl Into<u64>,
320 pad_byte: u8,
321 pad_len: u8,
322 ) {
323 assert!(pad_byte.is_ascii(), "padding byte must be ASCII");
324
325 let mut n = n.into();
326 let pad_len = pad_len.min(MAX_INTEGER_LEN);
327 let digits = pad_len.max(digits(n));
328 let mut remaining_digits = usize::from(digits);
329 let available = self
330 .available()
331 .get_mut(..remaining_digits)
332 .expect("u8 integer digits exceeds available buffer space");
333 while remaining_digits > 0 {
334 remaining_digits -= 1;
335 unsafe {
338 available
339 .get_unchecked_mut(remaining_digits)
340 .write(b'0' + ((n % 10) as u8));
341 }
342 n /= 10;
343 if n == 0 {
344 break;
345 }
346 }
347 while remaining_digits > 0 {
348 remaining_digits -= 1;
349 unsafe {
352 available.get_unchecked_mut(remaining_digits).write(pad_byte);
353 }
354 }
355 self.filled += u16::from(digits);
356 }
357
358 #[cfg_attr(feature = "perf-inline", inline(always))]
364 pub(crate) fn write_int1(&mut self, n: impl Into<u64>) {
365 let n = n.into();
366 assert!(n <= 9);
372 self.write_ascii_char(b'0' + (n as u8));
373 }
374
375 #[cfg_attr(feature = "perf-inline", inline(always))]
382 pub(crate) fn write_int_pad2(&mut self, n: impl Into<u64>) {
383 let n = n.into();
384 assert!(n <= 99);
393
394 let dst = self
395 .available()
396 .get_mut(..2)
397 .expect("padded 2 digit integer exceeds available buffer space");
398 let radix_offset = ((n % 100) * 2) as usize;
399 unsafe {
404 dst.get_unchecked_mut(0)
405 .write(*RADIX_100_ZERO.get_unchecked(radix_offset));
406 dst.get_unchecked_mut(1)
407 .write(*RADIX_100_ZERO.get_unchecked(radix_offset + 1));
408 }
409 self.filled += 2;
410 }
411
412 #[cfg_attr(feature = "perf-inline", inline(always))]
419 pub(crate) fn write_int_pad2_space(&mut self, n: impl Into<u64>) {
420 let n = n.into();
421 assert!(n <= 99);
430
431 let dst = self
432 .available()
433 .get_mut(..2)
434 .expect("padded 2 digit integer exceeds available buffer space");
435 let radix_offset = ((n % 100) * 2) as usize;
436 unsafe {
441 dst.get_unchecked_mut(0)
442 .write(*RADIX_100_SPACE.get_unchecked(radix_offset));
443 dst.get_unchecked_mut(1)
444 .write(*RADIX_100_SPACE.get_unchecked(radix_offset + 1));
445 }
446 self.filled += 2;
447 }
448
449 #[cfg_attr(feature = "perf-inline", inline(always))]
456 pub(crate) fn write_int_pad4(&mut self, n: impl Into<u64>) {
457 let mut n = n.into();
458 assert!(n <= 9999);
467
468 let dst = self
469 .available()
470 .get_mut(..4)
471 .expect("padded 4 digit integer exceeds available buffer space");
472
473 let radix_offset = ((n % 100) * 2) as usize;
474 unsafe {
479 dst.get_unchecked_mut(2)
480 .write(*RADIX_100_ZERO.get_unchecked(radix_offset));
481 dst.get_unchecked_mut(3)
482 .write(*RADIX_100_ZERO.get_unchecked(radix_offset + 1));
483 }
484
485 n /= 100;
486 let radix_offset = ((n % 100) * 2) as usize;
487 unsafe {
492 dst.get_unchecked_mut(0)
493 .write(*RADIX_100_ZERO.get_unchecked(radix_offset));
494 dst.get_unchecked_mut(1)
495 .write(*RADIX_100_ZERO.get_unchecked(radix_offset + 1));
496 }
497
498 self.filled += 4;
499 }
500
501 #[cfg_attr(feature = "perf-inline", inline(always))]
513 pub(crate) fn write_fraction(
514 &mut self,
515 precision: Option<u8>,
516 mut n: u32,
517 ) {
518 assert!(n <= 999_999_999);
519 let mut buf = ArrayBuffer::<MAX_PRECISION>::default();
520 for i in (0..MAX_PRECISION).rev() {
521 unsafe {
522 buf.data.get_unchecked_mut(i).write(b'0' + ((n % 10) as u8));
523 }
524 n /= 10;
525 }
526
527 let end = precision
528 .map(|p| p.min(MAX_PRECISION as u8))
529 .unwrap_or_else(|| {
530 let buf = unsafe { buf.assume_init() };
533 let mut end = MAX_PRECISION as u8;
534 while end > 0 && buf[usize::from(end) - 1] == b'0' {
535 end -= 1;
536 }
537 end
538 });
539
540 let buf = &buf.data[..usize::from(end)];
541 self.available()
542 .get_mut(..buf.len())
543 .expect("fraction exceeds available buffer space")
544 .copy_from_slice(buf);
545 self.filled += u16::from(end);
546 }
547
548 #[cfg_attr(feature = "perf-inline", inline(always))]
554 pub(crate) fn clear(&mut self) {
555 self.filled = 0;
556 }
557
558 #[cfg_attr(feature = "perf-inline", inline(always))]
560 pub(crate) fn filled(&self) -> &str {
561 let filled = unsafe { self.data.get_unchecked(..self.len()) };
565 unsafe {
571 core::str::from_utf8_unchecked(core::slice::from_raw_parts(
572 filled.as_ptr().cast::<u8>(),
573 self.len(),
574 ))
575 }
576 }
577
578 #[cfg_attr(feature = "perf-inline", inline(always))]
580 fn available(&mut self) -> &mut [MaybeUninit<u8>] {
581 unsafe { self.data.get_unchecked_mut(self.len()..) }
584 }
585
586 #[cfg_attr(feature = "perf-inline", inline(always))]
591 fn len(&self) -> usize {
592 usize::from(self.filled)
593 }
594
595 #[cfg_attr(feature = "perf-inline", inline(always))]
597 fn available_capacity(&self) -> usize {
598 self.capacity() - self.len()
599 }
600
601 #[cfg_attr(feature = "perf-inline", inline(always))]
603 fn capacity(&self) -> usize {
604 self.data.len()
605 }
606}
607
608impl<'data> From<&'data mut [u8]> for BorrowedBuffer<'data> {
619 #[cfg_attr(feature = "perf-inline", inline(always))]
620 fn from(data: &'data mut [u8]) -> BorrowedBuffer<'data> {
621 assert!(
622 data.len() <= MAX_CAPACITY,
623 "borrowed buffer only supports {MAX_CAPACITY} bytes"
624 );
625 let len = data.len();
626 let data: *mut MaybeUninit<u8> = data.as_mut_ptr().cast();
627 let data = unsafe { core::slice::from_raw_parts_mut(data, len) };
630 BorrowedBuffer { data, filled: 0 }
631 }
632}
633
634impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuffer<'data> {
640 #[cfg_attr(feature = "perf-inline", inline(always))]
641 fn from(data: &'data mut [MaybeUninit<u8>]) -> BorrowedBuffer<'data> {
642 assert!(
643 data.len() <= MAX_CAPACITY,
644 "borrowed buffer only supports {MAX_CAPACITY} bytes"
645 );
646 BorrowedBuffer { data, filled: 0 }
647 }
648}
649
650impl<'data, const N: usize> From<&'data mut [MaybeUninit<u8>; N]>
656 for BorrowedBuffer<'data>
657{
658 #[cfg_attr(feature = "perf-inline", inline(always))]
659 fn from(data: &'data mut [MaybeUninit<u8>; N]) -> BorrowedBuffer<'data> {
660 BorrowedBuffer::from(&mut data[..])
661 }
662}
663
664pub(crate) struct BorrowedWriter<'buffer, 'data, 'write> {
701 bbuf: &'buffer mut BorrowedBuffer<'data>,
702 wtr: &'write mut dyn Write,
703}
704
705impl<'buffer, 'data, 'write> BorrowedWriter<'buffer, 'data, 'write> {
706 #[cfg_attr(feature = "perf-inline", inline(always))]
714 pub(crate) fn new(
715 bbuf: &'buffer mut BorrowedBuffer<'data>,
716 wtr: &'write mut dyn Write,
717 ) -> BorrowedWriter<'buffer, 'data, 'write> {
718 assert!(bbuf.capacity() >= BROAD_MINIMUM_BUFFER_LEN);
719 BorrowedWriter { bbuf, wtr }
720 }
721
722 #[cfg_attr(feature = "perf-inline", inline(always))]
723 pub(crate) fn finish(self) -> Result<(), Error> {
724 self.wtr.write_str(self.bbuf.filled())?;
725 self.bbuf.clear();
726 Ok(())
727 }
728
729 #[cold]
730 #[inline(never)]
731 pub(crate) fn flush(&mut self) -> Result<(), Error> {
732 self.wtr.write_str(self.bbuf.filled())?;
733 self.bbuf.clear();
734 Ok(())
735 }
736
737 #[cfg_attr(feature = "perf-inline", inline(always))]
738 pub(crate) fn if_will_fill_then_flush(
739 &mut self,
740 additional: impl Into<usize>,
741 ) -> Result<(), Error> {
742 let n = additional.into();
743 if self.bbuf.len().saturating_add(n) > self.bbuf.capacity() {
744 self.flush()?;
745 }
746 Ok(())
747 }
748
749 #[cfg_attr(feature = "perf-inline", inline(always))]
750 pub(crate) fn write_str(&mut self, string: &str) -> Result<(), Error> {
751 if string.len() > self.bbuf.available_capacity() {
752 self.flush()?;
753 if string.len() > self.bbuf.available_capacity() {
754 return self.wtr.write_str(string);
755 }
756 }
757 self.bbuf.write_str(string);
758 Ok(())
759 }
760
761 #[cfg_attr(feature = "perf-inline", inline(always))]
762 pub(crate) fn write_char(&mut self, ch: char) -> Result<(), Error> {
763 self.if_will_fill_then_flush(ch.len_utf8())?;
764 self.bbuf.write_char(ch);
765 Ok(())
766 }
767
768 #[cfg_attr(feature = "perf-inline", inline(always))]
769 pub(crate) fn write_ascii_char(&mut self, byte: u8) -> Result<(), Error> {
770 if self.bbuf.available_capacity() == 0 {
771 self.flush()?;
772 }
773 self.bbuf.write_ascii_char(byte);
774 Ok(())
775 }
776
777 #[cfg_attr(feature = "perf-inline", inline(always))]
778 pub(crate) fn write_int_pad(
779 &mut self,
780 n: impl Into<u64>,
781 pad_byte: u8,
782 pad_len: u8,
783 ) -> Result<(), Error> {
784 let n = n.into();
785 let pad_len = pad_len.min(MAX_INTEGER_LEN);
786 let digits = pad_len.max(digits(n));
787 self.if_will_fill_then_flush(digits)?;
788 self.bbuf.write_int_pad(n, pad_byte, pad_len);
789 Ok(())
790 }
791
792 #[cfg_attr(feature = "perf-inline", inline(always))]
793 pub(crate) fn write_int_pad2(
794 &mut self,
795 n: impl Into<u64>,
796 ) -> Result<(), Error> {
797 self.if_will_fill_then_flush(2usize)?;
798 self.bbuf.write_int_pad2(n);
799 Ok(())
800 }
801
802 #[cfg_attr(feature = "perf-inline", inline(always))]
803 pub(crate) fn write_int_pad2_space(
804 &mut self,
805 n: impl Into<u64>,
806 ) -> Result<(), Error> {
807 self.if_will_fill_then_flush(2usize)?;
808 self.bbuf.write_int_pad2_space(n);
809 Ok(())
810 }
811
812 #[cfg_attr(feature = "perf-inline", inline(always))]
813 pub(crate) fn write_int_pad4(
814 &mut self,
815 n: impl Into<u64>,
816 ) -> Result<(), Error> {
817 self.if_will_fill_then_flush(4usize)?;
818 self.bbuf.write_int_pad4(n);
819 Ok(())
820 }
821
822 #[cfg_attr(feature = "perf-inline", inline(always))]
823 pub(crate) fn write_fraction(
824 &mut self,
825 precision: Option<u8>,
826 n: u32,
827 ) -> Result<(), Error> {
828 self.if_will_fill_then_flush(9usize)?;
836 self.bbuf.write_fraction(precision, n);
837 Ok(())
838 }
839}
840
841impl<'buffer, 'data, 'write> Write for BorrowedWriter<'buffer, 'data, 'write> {
847 fn write_str(&mut self, string: &str) -> Result<(), Error> {
848 BorrowedWriter::write_str(self, string)
849 }
850}
851
852#[cfg_attr(feature = "perf-inline", inline(always))]
861fn digits(n: u64) -> u8 {
862 match n {
866 0..=9 => 1,
867 10..=99 => 2,
868 100..=999 => 3,
869 1000..=9999 => 4,
870 _ => n.ilog10() as u8 + 1,
871 }
872}
873
874#[cfg(test)]
875mod tests {
876 use super::*;
877
878 #[test]
879 fn write_str_array() {
880 let mut buf = ArrayBuffer::<100>::default();
881 let mut bbuf = buf.as_borrowed();
882 bbuf.write_str("Hello, world!");
883 assert_eq!(bbuf.filled(), "Hello, world!");
884 let buf = bbuf.filled();
885 assert_eq!(buf, "Hello, world!");
886 }
887
888 #[test]
889 fn write_int_array() {
890 let mut buf = ArrayBuffer::<100>::default();
891 let mut bbuf = buf.as_borrowed();
892
893 bbuf.write_int(0u64);
894 {
895 let buf = bbuf.filled();
896 assert_eq!(buf, "0");
897 }
898
899 bbuf.clear();
900 bbuf.write_int(1u64);
901 {
902 let buf = bbuf.filled();
903 assert_eq!(buf, "1");
904 }
905
906 bbuf.clear();
907 bbuf.write_int(10u64);
908 {
909 let buf = bbuf.filled();
910 assert_eq!(buf, "10");
911 }
912
913 bbuf.clear();
914 bbuf.write_int(100u64);
915 {
916 let buf = bbuf.filled();
917 assert_eq!(buf, "100");
918 }
919
920 bbuf.clear();
921 bbuf.write_int(u64::MAX);
922 {
923 let buf = bbuf.filled();
924 assert_eq!(buf, "18446744073709551615");
925 }
926 }
927
928 #[test]
929 fn write_int_pad2() {
930 let mut buf = ArrayBuffer::<100>::default();
931 let mut bbuf = buf.as_borrowed();
932
933 bbuf.write_int_pad2(0u64);
934 {
935 let buf = bbuf.filled();
936 assert_eq!(buf, "00");
937 }
938
939 bbuf.clear();
940 bbuf.write_int_pad2(1u64);
941 {
942 let buf = bbuf.filled();
943 assert_eq!(buf, "01");
944 }
945
946 bbuf.clear();
947 bbuf.write_int_pad2(10u64);
948 {
949 let buf = bbuf.filled();
950 assert_eq!(buf, "10");
951 }
952
953 bbuf.clear();
954 bbuf.write_int_pad2(99u64);
955 {
956 let buf = bbuf.filled();
957 assert_eq!(buf, "99");
958 }
959 }
960
961 #[test]
962 #[should_panic]
963 fn write_int_pad2_panic() {
964 let mut buf = ArrayBuffer::<100>::default();
965 let mut bbuf = buf.as_borrowed();
966 bbuf.write_int_pad2(u64::MAX);
969 }
970
971 #[test]
972 fn write_int_pad4() {
973 let mut buf = ArrayBuffer::<100>::default();
974 let mut bbuf = buf.as_borrowed();
975
976 bbuf.write_int_pad4(0u64);
977 {
978 let buf = bbuf.filled();
979 assert_eq!(buf, "0000");
980 }
981
982 bbuf.clear();
983 bbuf.write_int_pad4(1u64);
984 {
985 let buf = bbuf.filled();
986 assert_eq!(buf, "0001");
987 }
988
989 bbuf.clear();
990 bbuf.write_int_pad4(10u64);
991 {
992 let buf = bbuf.filled();
993 assert_eq!(buf, "0010");
994 }
995
996 bbuf.clear();
997 bbuf.write_int_pad4(99u64);
998 {
999 let buf = bbuf.filled();
1000 assert_eq!(buf, "0099");
1001 }
1002
1003 bbuf.clear();
1004 bbuf.write_int_pad4(999u64);
1005 {
1006 let buf = bbuf.filled();
1007 assert_eq!(buf, "0999");
1008 }
1009
1010 bbuf.clear();
1011 bbuf.write_int_pad4(9999u64);
1012 {
1013 let buf = bbuf.filled();
1014 assert_eq!(buf, "9999");
1015 }
1016 }
1017
1018 #[test]
1019 #[should_panic]
1020 fn write_int_pad4_panic() {
1021 let mut buf = ArrayBuffer::<100>::default();
1022 let mut bbuf = buf.as_borrowed();
1023 bbuf.write_int_pad4(u64::MAX);
1026 }
1027
1028 #[test]
1029 fn write_int_pad_zero() {
1030 let mut buf = ArrayBuffer::<100>::default();
1031 let mut bbuf = buf.as_borrowed();
1032
1033 bbuf.write_int_pad(0u64, b'0', 0);
1034 {
1035 let buf = bbuf.filled();
1036 assert_eq!(buf, "0");
1037 }
1038
1039 bbuf.clear();
1040 bbuf.write_int_pad(0u64, b'0', 1);
1041 {
1042 let buf = bbuf.filled();
1043 assert_eq!(buf, "0");
1044 }
1045
1046 bbuf.clear();
1047 bbuf.write_int_pad(0u64, b'0', 2);
1048 {
1049 let buf = bbuf.filled();
1050 assert_eq!(buf, "00");
1051 }
1052
1053 bbuf.clear();
1054 bbuf.write_int_pad(0u64, b'0', 20);
1055 {
1056 let buf = bbuf.filled();
1057 assert_eq!(buf, "00000000000000000000");
1058 }
1059
1060 bbuf.clear();
1061 bbuf.write_int_pad(0u64, b'0', 21);
1063 {
1064 let buf = bbuf.filled();
1065 assert_eq!(buf, "00000000000000000000");
1066 }
1067
1068 bbuf.clear();
1069 bbuf.write_int_pad(0u64, b' ', 2);
1070 {
1071 let buf = bbuf.filled();
1072 assert_eq!(buf, " 0");
1073 }
1074 }
1075
1076 #[test]
1077 fn write_int_pad_one() {
1078 let mut buf = ArrayBuffer::<100>::default();
1079 let mut bbuf = buf.as_borrowed();
1080
1081 bbuf.write_int_pad(1u64, b'0', 0);
1082 {
1083 let buf = bbuf.filled();
1084 assert_eq!(buf, "1");
1085 }
1086
1087 bbuf.clear();
1088 bbuf.write_int_pad(1u64, b'0', 1);
1089 {
1090 let buf = bbuf.filled();
1091 assert_eq!(buf, "1");
1092 }
1093
1094 bbuf.clear();
1095 bbuf.write_int_pad(1u64, b'0', 2);
1096 {
1097 let buf = bbuf.filled();
1098 assert_eq!(buf, "01");
1099 }
1100
1101 bbuf.clear();
1102 bbuf.write_int_pad(1u64, b'0', 20);
1103 {
1104 let buf = bbuf.filled();
1105 assert_eq!(buf, "00000000000000000001");
1106 }
1107
1108 bbuf.clear();
1109 bbuf.write_int_pad(1u64, b'0', 21);
1111 {
1112 let buf = bbuf.filled();
1113 assert_eq!(buf, "00000000000000000001");
1114 }
1115
1116 bbuf.clear();
1117 bbuf.write_int_pad(1u64, b' ', 2);
1118 {
1119 let buf = bbuf.filled();
1120 assert_eq!(buf, " 1");
1121 }
1122 }
1123
1124 #[test]
1125 fn write_int_pad_max() {
1126 let mut buf = ArrayBuffer::<100>::default();
1127 let mut bbuf = buf.as_borrowed();
1128
1129 bbuf.write_int_pad(u64::MAX, b'0', 0);
1130 {
1131 let buf = bbuf.filled();
1132 assert_eq!(buf, "18446744073709551615");
1133 }
1134
1135 bbuf.clear();
1136 bbuf.write_int_pad(u64::MAX, b'0', 1);
1137 {
1138 let buf = bbuf.filled();
1139 assert_eq!(buf, "18446744073709551615");
1140 }
1141
1142 bbuf.clear();
1143 bbuf.write_int_pad(u64::MAX, b'0', 2);
1144 {
1145 let buf = bbuf.filled();
1146 assert_eq!(buf, "18446744073709551615");
1147 }
1148
1149 bbuf.clear();
1150 bbuf.write_int_pad(u64::MAX, b'0', 20);
1151 {
1152 let buf = bbuf.filled();
1153 assert_eq!(buf, "18446744073709551615");
1154 }
1155
1156 bbuf.clear();
1157 bbuf.write_int_pad(u64::MAX, b'0', 21);
1159 {
1160 let buf = bbuf.filled();
1161 assert_eq!(buf, "18446744073709551615");
1162 }
1163
1164 bbuf.clear();
1165 bbuf.write_int_pad(u64::MAX, b' ', 2);
1166 {
1167 let buf = bbuf.filled();
1168 assert_eq!(buf, "18446744073709551615");
1169 }
1170 }
1171
1172 #[test]
1173 #[should_panic]
1174 fn write_int_pad_non_ascii_panic() {
1175 let mut buf = ArrayBuffer::<100>::default();
1176 let mut bbuf = buf.as_borrowed();
1177 bbuf.write_int_pad(0u64, 0xFF, 0);
1178 }
1179
1180 #[test]
1181 #[should_panic]
1182 fn write_int_pad_insufficient_capacity_panic() {
1183 let mut buf = ArrayBuffer::<19>::default();
1184 let mut bbuf = buf.as_borrowed();
1185 bbuf.write_int_pad(0u64, b'0', 20);
1186 }
1187
1188 #[test]
1189 fn write_fraction_no_precision() {
1190 let mut buf = ArrayBuffer::<100>::default();
1191 let mut bbuf = buf.as_borrowed();
1192
1193 bbuf.write_fraction(None, 0);
1194 {
1195 let buf = bbuf.filled();
1196 assert_eq!(buf, "");
1197 }
1198
1199 bbuf.clear();
1200 bbuf.write_fraction(None, 1);
1201 {
1202 let buf = bbuf.filled();
1203 assert_eq!(buf, "000000001");
1204 }
1205
1206 bbuf.clear();
1207 bbuf.write_fraction(None, 123_000_000);
1208 {
1209 let buf = bbuf.filled();
1210 assert_eq!(buf, "123");
1211 }
1212
1213 bbuf.clear();
1214 bbuf.write_fraction(None, 999_999_999);
1215 {
1216 let buf = bbuf.filled();
1217 assert_eq!(buf, "999999999");
1218 }
1219 }
1220
1221 #[test]
1222 fn write_fraction_precision() {
1223 let mut buf = ArrayBuffer::<100>::default();
1224 let mut bbuf = buf.as_borrowed();
1225
1226 bbuf.write_fraction(Some(0), 0);
1227 {
1228 let buf = bbuf.filled();
1229 assert_eq!(buf, "");
1230 }
1231
1232 bbuf.clear();
1233 bbuf.write_fraction(Some(1), 0);
1234 {
1235 let buf = bbuf.filled();
1236 assert_eq!(buf, "0");
1237 }
1238
1239 bbuf.clear();
1240 bbuf.write_fraction(Some(9), 0);
1241 {
1242 let buf = bbuf.filled();
1243 assert_eq!(buf, "000000000");
1244 }
1245
1246 bbuf.clear();
1247 bbuf.write_fraction(Some(0), 1);
1248 {
1249 let buf = bbuf.filled();
1250 assert_eq!(buf, "");
1251 }
1252
1253 bbuf.clear();
1254 bbuf.write_fraction(Some(9), 1);
1255 {
1256 let buf = bbuf.filled();
1257 assert_eq!(buf, "000000001");
1258 }
1259
1260 bbuf.clear();
1261 bbuf.write_fraction(Some(0), 123_000_000);
1262 {
1263 let buf = bbuf.filled();
1264 assert_eq!(buf, "");
1265 }
1266
1267 bbuf.clear();
1268 bbuf.write_fraction(Some(1), 123_000_000);
1269 {
1270 let buf = bbuf.filled();
1271 assert_eq!(buf, "1");
1272 }
1273
1274 bbuf.clear();
1275 bbuf.write_fraction(Some(2), 123_000_000);
1276 {
1277 let buf = bbuf.filled();
1278 assert_eq!(buf, "12");
1279 }
1280
1281 bbuf.clear();
1282 bbuf.write_fraction(Some(3), 123_000_000);
1283 {
1284 let buf = bbuf.filled();
1285 assert_eq!(buf, "123");
1286 }
1287
1288 bbuf.clear();
1289 bbuf.write_fraction(Some(6), 123_000_000);
1290 {
1291 let buf = bbuf.filled();
1292 assert_eq!(buf, "123000");
1293 }
1294
1295 bbuf.clear();
1296 bbuf.write_fraction(Some(9), 123_000_000);
1297 {
1298 let buf = bbuf.filled();
1299 assert_eq!(buf, "123000000");
1300 }
1301
1302 bbuf.clear();
1303 bbuf.write_fraction(Some(10), 123_000_000);
1305 {
1306 let buf = bbuf.filled();
1307 assert_eq!(buf, "123000000");
1308 }
1309
1310 bbuf.clear();
1311 bbuf.write_fraction(Some(0), 999_999_999);
1312 {
1313 let buf = bbuf.filled();
1314 assert_eq!(buf, "");
1315 }
1316
1317 bbuf.clear();
1318 bbuf.write_fraction(Some(1), 999_999_999);
1319 {
1320 let buf = bbuf.filled();
1321 assert_eq!(buf, "9");
1322 }
1323
1324 bbuf.clear();
1325 bbuf.write_fraction(Some(3), 999_999_999);
1326 {
1327 let buf = bbuf.filled();
1328 assert_eq!(buf, "999");
1329 }
1330
1331 bbuf.clear();
1332 bbuf.write_fraction(Some(6), 999_999_999);
1333 {
1334 let buf = bbuf.filled();
1335 assert_eq!(buf, "999999");
1336 }
1337
1338 bbuf.clear();
1339 bbuf.write_fraction(Some(9), 999_999_999);
1340 {
1341 let buf = bbuf.filled();
1342 assert_eq!(buf, "999999999");
1343 }
1344 }
1345
1346 #[test]
1347 #[should_panic]
1348 fn write_fraction_too_big_panic() {
1349 let mut buf = ArrayBuffer::<100>::default();
1350 let mut bbuf = buf.as_borrowed();
1351 bbuf.write_fraction(None, 1_000_000_000);
1352 }
1353}