Skip to main content

ferrilog_core/encode/
primitives.rs

1use std::fmt::Write as _;
2
3use super::{
4    Encode, EncodeFast, FORMAT_ALIGN_NONE, FORMAT_ALIGN_RIGHT, FORMAT_PRECISION_NONE,
5    format::{
6        VecWriter, append_binary_u64_padded_const, append_const_float_body,
7        append_display_with_spec, append_float_with_spec, append_i32_decimal_with_spec,
8        append_i64_decimal_with_spec, append_integer_with_spec_cast,
9        append_lower_hex_u64_padded_const, append_octal_u64_padded_const, append_padded_const,
10        append_ryu_float, append_u32_decimal_with_spec, append_u64_decimal_with_spec,
11        append_upper_hex_u64_padded_const,
12    },
13    traits::{
14        EncodeBinary, EncodeConstBinaryFormat, EncodeConstDefaultFormat, EncodeConstFloatFormat,
15        EncodeConstLowerHexFormat, EncodeConstOctalFormat, EncodeConstUpperHexFormat,
16        EncodeLowerHex, EncodeOctal, EncodeUpperHex,
17    },
18};
19use crate::number_format;
20
21// --- Layer 1: Fast Primitive Path ---
22
23macro_rules! impl_integer_encode {
24    ($type:ty, $append_function:path, $cast:expr, $append_decimal:expr) => {
25        impl Encode for $type {
26            const ENCODED_SIZE_HINT: usize = std::mem::size_of::<$type>();
27
28            #[inline(always)]
29            fn encoded_size(&self) -> usize {
30                std::mem::size_of::<$type>()
31            }
32
33            #[inline(always)]
34            unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
35                unsafe {
36                    buffer.add(*offset).cast::<$type>().write_unaligned(*self);
37                }
38                *offset += std::mem::size_of::<$type>();
39            }
40
41            #[inline(always)]
42            unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
43                unsafe {
44                    buffer.add(offset).cast::<$type>().write_unaligned(*self);
45                }
46            }
47
48            #[inline]
49            unsafe fn decode_and_format(
50                buffer: *const u8,
51                offset: &mut usize,
52                output: &mut Vec<u8>,
53                format_spec: &str,
54            ) {
55                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
56                *offset += std::mem::size_of::<$type>();
57                if format_spec.is_empty() {
58                    $append_function(output, value);
59                } else {
60                    append_integer_with_spec_cast(
61                        output,
62                        value,
63                        ($cast)(value),
64                        format_spec,
65                        |output, spec| ($append_decimal)(output, value, spec),
66                    );
67                }
68            }
69
70            #[inline]
71            unsafe fn decode_and_format_at_offset(
72                buffer: *const u8,
73                offset: usize,
74                output: &mut Vec<u8>,
75                format_spec: &str,
76            ) {
77                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
78                if format_spec.is_empty() {
79                    $append_function(output, value);
80                } else {
81                    append_integer_with_spec_cast(
82                        output,
83                        value,
84                        ($cast)(value),
85                        format_spec,
86                        |output, spec| ($append_decimal)(output, value, spec),
87                    );
88                }
89            }
90        }
91
92        unsafe impl EncodeFast for $type {
93            #[inline(always)]
94            unsafe fn decode_and_append_fast_at_offset(
95                buffer: *const u8,
96                offset: usize,
97                output: &mut Vec<u8>,
98            ) {
99                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
100                $append_function(output, value);
101            }
102        }
103    };
104}
105
106// Integer formatting uses the dedicated number_format path
107impl_integer_encode!(
108    i32,
109    number_format::append_i32,
110    |value: i32| (value as u32) as u64,
111    append_i32_decimal_with_spec
112);
113impl_integer_encode!(
114    u32,
115    number_format::append_u32,
116    |value: u32| value as u64,
117    append_u32_decimal_with_spec
118);
119impl_integer_encode!(
120    i64,
121    number_format::append_i64,
122    |value: i64| value as u64,
123    append_i64_decimal_with_spec
124);
125impl_integer_encode!(
126    u64,
127    number_format::append_u64,
128    |value: u64| value,
129    append_u64_decimal_with_spec
130);
131impl_integer_encode!(
132    usize,
133    number_format::append_u64_from_usize,
134    |value: usize| value as u64,
135    |output, value, spec| append_u64_decimal_with_spec(output, value as u64, spec)
136);
137impl_integer_encode!(
138    isize,
139    number_format::append_i64_from_isize,
140    |value: isize| { (value as usize) as u64 },
141    |output, value, spec| append_i64_decimal_with_spec(output, value as i64, spec)
142);
143macro_rules! impl_unsigned_integer_format_traits {
144    ($type:ty, $read:expr) => {
145        impl EncodeLowerHex for $type {
146            #[inline]
147            unsafe fn decode_append_lower_hex<const ALTERNATE: bool>(
148                buffer: *const u8,
149                offset: &mut usize,
150                output: &mut Vec<u8>,
151            ) {
152                let value = ($read)(buffer, offset);
153                append_lower_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
154                    output,
155                    value as u64,
156                );
157            }
158
159            #[inline]
160            unsafe fn decode_append_lower_hex_at_offset<const ALTERNATE: bool>(
161                buffer: *const u8,
162                offset: usize,
163                output: &mut Vec<u8>,
164            ) {
165                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
166                append_lower_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
167                    output,
168                    value as u64,
169                );
170            }
171        }
172
173        impl EncodeUpperHex for $type {
174            #[inline]
175            unsafe fn decode_append_upper_hex<const ALTERNATE: bool>(
176                buffer: *const u8,
177                offset: &mut usize,
178                output: &mut Vec<u8>,
179            ) {
180                let value = ($read)(buffer, offset);
181                append_upper_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
182                    output,
183                    value as u64,
184                );
185            }
186
187            #[inline]
188            unsafe fn decode_append_upper_hex_at_offset<const ALTERNATE: bool>(
189                buffer: *const u8,
190                offset: usize,
191                output: &mut Vec<u8>,
192            ) {
193                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
194                append_upper_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
195                    output,
196                    value as u64,
197                );
198            }
199        }
200
201        impl EncodeBinary for $type {
202            #[inline]
203            unsafe fn decode_append_binary<const ALTERNATE: bool>(
204                buffer: *const u8,
205                offset: &mut usize,
206                output: &mut Vec<u8>,
207            ) {
208                let value = ($read)(buffer, offset);
209                append_binary_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
210                    output,
211                    value as u64,
212                );
213            }
214
215            #[inline]
216            unsafe fn decode_append_binary_at_offset<const ALTERNATE: bool>(
217                buffer: *const u8,
218                offset: usize,
219                output: &mut Vec<u8>,
220            ) {
221                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
222                append_binary_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
223                    output,
224                    value as u64,
225                );
226            }
227        }
228
229        impl EncodeOctal for $type {
230            #[inline]
231            unsafe fn decode_append_octal<const ALTERNATE: bool>(
232                buffer: *const u8,
233                offset: &mut usize,
234                output: &mut Vec<u8>,
235            ) {
236                let value = ($read)(buffer, offset);
237                append_octal_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
238                    output,
239                    value as u64,
240                );
241            }
242
243            #[inline]
244            unsafe fn decode_append_octal_at_offset<const ALTERNATE: bool>(
245                buffer: *const u8,
246                offset: usize,
247                output: &mut Vec<u8>,
248            ) {
249                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
250                append_octal_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
251                    output,
252                    value as u64,
253                );
254            }
255        }
256    };
257}
258
259macro_rules! impl_signed_integer_format_traits {
260    ($type:ty, $read:expr, $cast:expr) => {
261        impl EncodeLowerHex for $type {
262            #[inline]
263            unsafe fn decode_append_lower_hex<const ALTERNATE: bool>(
264                buffer: *const u8,
265                offset: &mut usize,
266                output: &mut Vec<u8>,
267            ) {
268                let value = ($read)(buffer, offset);
269                append_lower_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
270                    output,
271                    ($cast)(value),
272                );
273            }
274
275            #[inline]
276            unsafe fn decode_append_lower_hex_at_offset<const ALTERNATE: bool>(
277                buffer: *const u8,
278                offset: usize,
279                output: &mut Vec<u8>,
280            ) {
281                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
282                append_lower_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
283                    output,
284                    ($cast)(value),
285                );
286            }
287        }
288
289        impl EncodeUpperHex for $type {
290            #[inline]
291            unsafe fn decode_append_upper_hex<const ALTERNATE: bool>(
292                buffer: *const u8,
293                offset: &mut usize,
294                output: &mut Vec<u8>,
295            ) {
296                let value = ($read)(buffer, offset);
297                append_upper_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
298                    output,
299                    ($cast)(value),
300                );
301            }
302
303            #[inline]
304            unsafe fn decode_append_upper_hex_at_offset<const ALTERNATE: bool>(
305                buffer: *const u8,
306                offset: usize,
307                output: &mut Vec<u8>,
308            ) {
309                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
310                append_upper_hex_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
311                    output,
312                    ($cast)(value),
313                );
314            }
315        }
316
317        impl EncodeBinary for $type {
318            #[inline]
319            unsafe fn decode_append_binary<const ALTERNATE: bool>(
320                buffer: *const u8,
321                offset: &mut usize,
322                output: &mut Vec<u8>,
323            ) {
324                let value = ($read)(buffer, offset);
325                append_binary_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
326                    output,
327                    ($cast)(value),
328                );
329            }
330
331            #[inline]
332            unsafe fn decode_append_binary_at_offset<const ALTERNATE: bool>(
333                buffer: *const u8,
334                offset: usize,
335                output: &mut Vec<u8>,
336            ) {
337                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
338                append_binary_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
339                    output,
340                    ($cast)(value),
341                );
342            }
343        }
344
345        impl EncodeOctal for $type {
346            #[inline]
347            unsafe fn decode_append_octal<const ALTERNATE: bool>(
348                buffer: *const u8,
349                offset: &mut usize,
350                output: &mut Vec<u8>,
351            ) {
352                let value = ($read)(buffer, offset);
353                append_octal_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
354                    output,
355                    ($cast)(value),
356                );
357            }
358
359            #[inline]
360            unsafe fn decode_append_octal_at_offset<const ALTERNATE: bool>(
361                buffer: *const u8,
362                offset: usize,
363                output: &mut Vec<u8>,
364            ) {
365                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
366                append_octal_u64_padded_const::<b' ', { FORMAT_ALIGN_NONE }, 0, false, ALTERNATE>(
367                    output,
368                    ($cast)(value),
369                );
370            }
371        }
372    };
373}
374
375impl_signed_integer_format_traits!(
376    i32,
377    |buffer: *const u8, offset: &mut usize| {
378        let value = unsafe { buffer.add(*offset).cast::<i32>().read_unaligned() };
379        *offset += std::mem::size_of::<i32>();
380        value
381    },
382    |value: i32| (value as u32) as u64
383);
384impl_unsigned_integer_format_traits!(u32, |buffer: *const u8, offset: &mut usize| {
385    let value = unsafe { buffer.add(*offset).cast::<u32>().read_unaligned() };
386    *offset += std::mem::size_of::<u32>();
387    value
388});
389impl_signed_integer_format_traits!(
390    i64,
391    |buffer: *const u8, offset: &mut usize| {
392        let value = unsafe { buffer.add(*offset).cast::<i64>().read_unaligned() };
393        *offset += std::mem::size_of::<i64>();
394        value
395    },
396    |value: i64| value as u64
397);
398impl_unsigned_integer_format_traits!(u64, |buffer: *const u8, offset: &mut usize| {
399    let value = unsafe { buffer.add(*offset).cast::<u64>().read_unaligned() };
400    *offset += std::mem::size_of::<u64>();
401    value
402});
403impl_unsigned_integer_format_traits!(usize, |buffer: *const u8, offset: &mut usize| {
404    let value = unsafe { buffer.add(*offset).cast::<usize>().read_unaligned() };
405    *offset += std::mem::size_of::<usize>();
406    value
407});
408impl_signed_integer_format_traits!(
409    isize,
410    |buffer: *const u8, offset: &mut usize| {
411        let value = unsafe { buffer.add(*offset).cast::<isize>().read_unaligned() };
412        *offset += std::mem::size_of::<isize>();
413        value
414    },
415    |value: isize| (value as usize) as u64
416);
417
418// Small integers are promoted to i64/u64
419impl Encode for i8 {
420    const ENCODED_SIZE_HINT: usize = 1;
421
422    #[inline(always)]
423    fn encoded_size(&self) -> usize {
424        1
425    }
426
427    #[inline(always)]
428    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
429        unsafe {
430            *buffer.add(*offset) = *self as u8;
431        }
432        *offset += 1;
433    }
434
435    #[inline(always)]
436    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
437        unsafe {
438            *buffer.add(offset) = *self as u8;
439        }
440    }
441
442    #[inline]
443    unsafe fn decode_and_format(
444        buffer: *const u8,
445        offset: &mut usize,
446        output: &mut Vec<u8>,
447        format_spec: &str,
448    ) {
449        let value = unsafe { *buffer.add(*offset) } as i8;
450        *offset += 1;
451        if format_spec.is_empty() {
452            number_format::append_i32(output, value as i32);
453        } else {
454            append_integer_with_spec_cast(
455                output,
456                value,
457                (value as u8) as u64,
458                format_spec,
459                |output, spec| append_i32_decimal_with_spec(output, value as i32, spec),
460            );
461        }
462    }
463}
464unsafe impl EncodeFast for i8 {}
465
466impl_signed_integer_format_traits!(
467    i8,
468    |buffer: *const u8, offset: &mut usize| {
469        let value = unsafe { *buffer.add(*offset) } as i8;
470        *offset += 1;
471        value
472    },
473    |value: i8| (value as u8) as u64
474);
475
476impl Encode for u8 {
477    const ENCODED_SIZE_HINT: usize = 1;
478
479    #[inline(always)]
480    fn encoded_size(&self) -> usize {
481        1
482    }
483
484    #[inline(always)]
485    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
486        unsafe {
487            *buffer.add(*offset) = *self;
488        }
489        *offset += 1;
490    }
491
492    #[inline(always)]
493    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
494        unsafe {
495            *buffer.add(offset) = *self;
496        }
497    }
498
499    #[inline]
500    unsafe fn decode_and_format(
501        buffer: *const u8,
502        offset: &mut usize,
503        output: &mut Vec<u8>,
504        format_spec: &str,
505    ) {
506        let value = unsafe { *buffer.add(*offset) };
507        *offset += 1;
508        if format_spec.is_empty() {
509            number_format::append_u32(output, value as u32);
510        } else {
511            append_integer_with_spec_cast(
512                output,
513                value,
514                value as u64,
515                format_spec,
516                |output, spec| append_u32_decimal_with_spec(output, value as u32, spec),
517            );
518        }
519    }
520}
521unsafe impl EncodeFast for u8 {}
522
523impl_unsigned_integer_format_traits!(u8, |buffer: *const u8, offset: &mut usize| {
524    let value = unsafe { *buffer.add(*offset) };
525    *offset += 1;
526    value
527});
528
529impl Encode for i16 {
530    const ENCODED_SIZE_HINT: usize = 2;
531
532    #[inline(always)]
533    fn encoded_size(&self) -> usize {
534        2
535    }
536
537    #[inline(always)]
538    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
539        unsafe {
540            buffer.add(*offset).cast::<i16>().write_unaligned(*self);
541        }
542        *offset += 2;
543    }
544
545    #[inline(always)]
546    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
547        unsafe {
548            buffer.add(offset).cast::<i16>().write_unaligned(*self);
549        }
550    }
551
552    #[inline]
553    unsafe fn decode_and_format(
554        buffer: *const u8,
555        offset: &mut usize,
556        output: &mut Vec<u8>,
557        format_spec: &str,
558    ) {
559        let value = unsafe { buffer.add(*offset).cast::<i16>().read_unaligned() };
560        *offset += 2;
561        if format_spec.is_empty() {
562            number_format::append_i32(output, value as i32);
563        } else {
564            append_integer_with_spec_cast(
565                output,
566                value,
567                (value as u16) as u64,
568                format_spec,
569                |output, spec| append_i32_decimal_with_spec(output, value as i32, spec),
570            );
571        }
572    }
573}
574unsafe impl EncodeFast for i16 {}
575
576impl_signed_integer_format_traits!(
577    i16,
578    |buffer: *const u8, offset: &mut usize| {
579        let value = unsafe { buffer.add(*offset).cast::<i16>().read_unaligned() };
580        *offset += 2;
581        value
582    },
583    |value: i16| (value as u16) as u64
584);
585
586impl Encode for u16 {
587    const ENCODED_SIZE_HINT: usize = 2;
588
589    #[inline(always)]
590    fn encoded_size(&self) -> usize {
591        2
592    }
593
594    #[inline(always)]
595    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
596        unsafe {
597            buffer.add(*offset).cast::<u16>().write_unaligned(*self);
598        }
599        *offset += 2;
600    }
601
602    #[inline(always)]
603    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
604        unsafe {
605            buffer.add(offset).cast::<u16>().write_unaligned(*self);
606        }
607    }
608
609    #[inline]
610    unsafe fn decode_and_format(
611        buffer: *const u8,
612        offset: &mut usize,
613        output: &mut Vec<u8>,
614        format_spec: &str,
615    ) {
616        let value = unsafe { buffer.add(*offset).cast::<u16>().read_unaligned() };
617        *offset += 2;
618        if format_spec.is_empty() {
619            number_format::append_u32(output, value as u32);
620        } else {
621            append_integer_with_spec_cast(
622                output,
623                value,
624                value as u64,
625                format_spec,
626                |output, spec| append_u32_decimal_with_spec(output, value as u32, spec),
627            );
628        }
629    }
630}
631unsafe impl EncodeFast for u16 {}
632
633impl_unsigned_integer_format_traits!(u16, |buffer: *const u8, offset: &mut usize| {
634    let value = unsafe { buffer.add(*offset).cast::<u16>().read_unaligned() };
635    *offset += 2;
636    value
637});
638
639macro_rules! impl_const_default_integer_format {
640    ($type:ty, $cast:expr, $append:ident) => {
641        impl EncodeConstDefaultFormat for $type {
642            #[inline]
643            unsafe fn decode_append_default_format<
644                const FILL: u8,
645                const ALIGN: u8,
646                const WIDTH: usize,
647                const PRECISION: usize,
648                const ZERO_PAD: bool,
649            >(
650                buffer: *const u8,
651                offset: &mut usize,
652                output: &mut Vec<u8>,
653            ) {
654                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
655                *offset += std::mem::size_of::<$type>();
656                let _ = PRECISION;
657                number_format::$append::<FILL, ALIGN, WIDTH, ZERO_PAD>(output, ($cast)(value));
658            }
659
660            #[inline]
661            unsafe fn decode_append_default_format_at_offset<
662                const FILL: u8,
663                const ALIGN: u8,
664                const WIDTH: usize,
665                const PRECISION: usize,
666                const ZERO_PAD: bool,
667            >(
668                buffer: *const u8,
669                offset: usize,
670                output: &mut Vec<u8>,
671            ) {
672                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
673                let _ = PRECISION;
674                number_format::$append::<FILL, ALIGN, WIDTH, ZERO_PAD>(output, ($cast)(value));
675            }
676        }
677    };
678}
679
680impl_const_default_integer_format!(i32, |value: i32| value, append_i32_padded_const);
681impl_const_default_integer_format!(u32, |value: u32| value, append_u32_padded_const);
682impl_const_default_integer_format!(i64, |value: i64| value, append_i64_padded_const);
683impl_const_default_integer_format!(u64, |value: u64| value, append_u64_padded_const);
684impl_const_default_integer_format!(usize, |value: usize| value as u64, append_u64_padded_const);
685impl_const_default_integer_format!(isize, |value: isize| value as i64, append_i64_padded_const);
686impl_const_default_integer_format!(i8, |value: i8| value as i32, append_i32_padded_const);
687impl_const_default_integer_format!(u8, |value: u8| value as u32, append_u32_padded_const);
688impl_const_default_integer_format!(i16, |value: i16| value as i32, append_i32_padded_const);
689impl_const_default_integer_format!(u16, |value: u16| value as u32, append_u32_padded_const);
690
691macro_rules! impl_const_typed_unsigned_integer_format_traits {
692    ($type:ty, $cast:expr) => {
693        impl EncodeConstLowerHexFormat for $type {
694            #[inline]
695            unsafe fn decode_append_lower_hex_format<
696                const FILL: u8,
697                const ALIGN: u8,
698                const WIDTH: usize,
699                const ZERO_PAD: bool,
700                const ALTERNATE: bool,
701            >(
702                buffer: *const u8,
703                offset: &mut usize,
704                output: &mut Vec<u8>,
705            ) {
706                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
707                *offset += std::mem::size_of::<$type>();
708                append_lower_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
709                    output,
710                    ($cast)(value),
711                );
712            }
713
714            #[inline]
715            unsafe fn decode_append_lower_hex_format_at_offset<
716                const FILL: u8,
717                const ALIGN: u8,
718                const WIDTH: usize,
719                const ZERO_PAD: bool,
720                const ALTERNATE: bool,
721            >(
722                buffer: *const u8,
723                offset: usize,
724                output: &mut Vec<u8>,
725            ) {
726                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
727                append_lower_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
728                    output,
729                    ($cast)(value),
730                );
731            }
732        }
733
734        impl EncodeConstUpperHexFormat for $type {
735            #[inline]
736            unsafe fn decode_append_upper_hex_format<
737                const FILL: u8,
738                const ALIGN: u8,
739                const WIDTH: usize,
740                const ZERO_PAD: bool,
741                const ALTERNATE: bool,
742            >(
743                buffer: *const u8,
744                offset: &mut usize,
745                output: &mut Vec<u8>,
746            ) {
747                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
748                *offset += std::mem::size_of::<$type>();
749                append_upper_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
750                    output,
751                    ($cast)(value),
752                );
753            }
754
755            #[inline]
756            unsafe fn decode_append_upper_hex_format_at_offset<
757                const FILL: u8,
758                const ALIGN: u8,
759                const WIDTH: usize,
760                const ZERO_PAD: bool,
761                const ALTERNATE: bool,
762            >(
763                buffer: *const u8,
764                offset: usize,
765                output: &mut Vec<u8>,
766            ) {
767                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
768                append_upper_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
769                    output,
770                    ($cast)(value),
771                );
772            }
773        }
774
775        impl EncodeConstBinaryFormat for $type {
776            #[inline]
777            unsafe fn decode_append_binary_format<
778                const FILL: u8,
779                const ALIGN: u8,
780                const WIDTH: usize,
781                const ZERO_PAD: bool,
782                const ALTERNATE: bool,
783            >(
784                buffer: *const u8,
785                offset: &mut usize,
786                output: &mut Vec<u8>,
787            ) {
788                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
789                *offset += std::mem::size_of::<$type>();
790                append_binary_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
791                    output,
792                    ($cast)(value),
793                );
794            }
795
796            #[inline]
797            unsafe fn decode_append_binary_format_at_offset<
798                const FILL: u8,
799                const ALIGN: u8,
800                const WIDTH: usize,
801                const ZERO_PAD: bool,
802                const ALTERNATE: bool,
803            >(
804                buffer: *const u8,
805                offset: usize,
806                output: &mut Vec<u8>,
807            ) {
808                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
809                append_binary_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
810                    output,
811                    ($cast)(value),
812                );
813            }
814        }
815
816        impl EncodeConstOctalFormat for $type {
817            #[inline]
818            unsafe fn decode_append_octal_format<
819                const FILL: u8,
820                const ALIGN: u8,
821                const WIDTH: usize,
822                const ZERO_PAD: bool,
823                const ALTERNATE: bool,
824            >(
825                buffer: *const u8,
826                offset: &mut usize,
827                output: &mut Vec<u8>,
828            ) {
829                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
830                *offset += std::mem::size_of::<$type>();
831                append_octal_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
832                    output,
833                    ($cast)(value),
834                );
835            }
836
837            #[inline]
838            unsafe fn decode_append_octal_format_at_offset<
839                const FILL: u8,
840                const ALIGN: u8,
841                const WIDTH: usize,
842                const ZERO_PAD: bool,
843                const ALTERNATE: bool,
844            >(
845                buffer: *const u8,
846                offset: usize,
847                output: &mut Vec<u8>,
848            ) {
849                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
850                append_octal_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
851                    output,
852                    ($cast)(value),
853                );
854            }
855        }
856    };
857}
858
859macro_rules! impl_const_typed_signed_integer_format_traits {
860    ($type:ty, $cast:expr) => {
861        impl EncodeConstLowerHexFormat for $type {
862            #[inline]
863            unsafe fn decode_append_lower_hex_format<
864                const FILL: u8,
865                const ALIGN: u8,
866                const WIDTH: usize,
867                const ZERO_PAD: bool,
868                const ALTERNATE: bool,
869            >(
870                buffer: *const u8,
871                offset: &mut usize,
872                output: &mut Vec<u8>,
873            ) {
874                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
875                *offset += std::mem::size_of::<$type>();
876                append_lower_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
877                    output,
878                    ($cast)(value),
879                );
880            }
881
882            #[inline]
883            unsafe fn decode_append_lower_hex_format_at_offset<
884                const FILL: u8,
885                const ALIGN: u8,
886                const WIDTH: usize,
887                const ZERO_PAD: bool,
888                const ALTERNATE: bool,
889            >(
890                buffer: *const u8,
891                offset: usize,
892                output: &mut Vec<u8>,
893            ) {
894                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
895                append_lower_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
896                    output,
897                    ($cast)(value),
898                );
899            }
900        }
901
902        impl EncodeConstUpperHexFormat for $type {
903            #[inline]
904            unsafe fn decode_append_upper_hex_format<
905                const FILL: u8,
906                const ALIGN: u8,
907                const WIDTH: usize,
908                const ZERO_PAD: bool,
909                const ALTERNATE: bool,
910            >(
911                buffer: *const u8,
912                offset: &mut usize,
913                output: &mut Vec<u8>,
914            ) {
915                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
916                *offset += std::mem::size_of::<$type>();
917                append_upper_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
918                    output,
919                    ($cast)(value),
920                );
921            }
922
923            #[inline]
924            unsafe fn decode_append_upper_hex_format_at_offset<
925                const FILL: u8,
926                const ALIGN: u8,
927                const WIDTH: usize,
928                const ZERO_PAD: bool,
929                const ALTERNATE: bool,
930            >(
931                buffer: *const u8,
932                offset: usize,
933                output: &mut Vec<u8>,
934            ) {
935                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
936                append_upper_hex_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
937                    output,
938                    ($cast)(value),
939                );
940            }
941        }
942
943        impl EncodeConstBinaryFormat for $type {
944            #[inline]
945            unsafe fn decode_append_binary_format<
946                const FILL: u8,
947                const ALIGN: u8,
948                const WIDTH: usize,
949                const ZERO_PAD: bool,
950                const ALTERNATE: bool,
951            >(
952                buffer: *const u8,
953                offset: &mut usize,
954                output: &mut Vec<u8>,
955            ) {
956                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
957                *offset += std::mem::size_of::<$type>();
958                append_binary_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
959                    output,
960                    ($cast)(value),
961                );
962            }
963
964            #[inline]
965            unsafe fn decode_append_binary_format_at_offset<
966                const FILL: u8,
967                const ALIGN: u8,
968                const WIDTH: usize,
969                const ZERO_PAD: bool,
970                const ALTERNATE: bool,
971            >(
972                buffer: *const u8,
973                offset: usize,
974                output: &mut Vec<u8>,
975            ) {
976                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
977                append_binary_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
978                    output,
979                    ($cast)(value),
980                );
981            }
982        }
983
984        impl EncodeConstOctalFormat for $type {
985            #[inline]
986            unsafe fn decode_append_octal_format<
987                const FILL: u8,
988                const ALIGN: u8,
989                const WIDTH: usize,
990                const ZERO_PAD: bool,
991                const ALTERNATE: bool,
992            >(
993                buffer: *const u8,
994                offset: &mut usize,
995                output: &mut Vec<u8>,
996            ) {
997                let value = unsafe { buffer.add(*offset).cast::<$type>().read_unaligned() };
998                *offset += std::mem::size_of::<$type>();
999                append_octal_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
1000                    output,
1001                    ($cast)(value),
1002                );
1003            }
1004
1005            #[inline]
1006            unsafe fn decode_append_octal_format_at_offset<
1007                const FILL: u8,
1008                const ALIGN: u8,
1009                const WIDTH: usize,
1010                const ZERO_PAD: bool,
1011                const ALTERNATE: bool,
1012            >(
1013                buffer: *const u8,
1014                offset: usize,
1015                output: &mut Vec<u8>,
1016            ) {
1017                let value = unsafe { buffer.add(offset).cast::<$type>().read_unaligned() };
1018                append_octal_u64_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, ALTERNATE>(
1019                    output,
1020                    ($cast)(value),
1021                );
1022            }
1023        }
1024    };
1025}
1026
1027impl_const_typed_signed_integer_format_traits!(i32, |value: i32| (value as u32) as u64);
1028impl_const_typed_unsigned_integer_format_traits!(u32, |value: u32| value as u64);
1029impl_const_typed_signed_integer_format_traits!(i64, |value: i64| value as u64);
1030impl_const_typed_unsigned_integer_format_traits!(u64, |value: u64| value);
1031impl_const_typed_unsigned_integer_format_traits!(usize, |value: usize| value as u64);
1032impl_const_typed_signed_integer_format_traits!(isize, |value: isize| (value as usize) as u64);
1033impl_const_typed_signed_integer_format_traits!(i8, |value: i8| (value as u8) as u64);
1034impl_const_typed_unsigned_integer_format_traits!(u8, |value: u8| value as u64);
1035impl_const_typed_signed_integer_format_traits!(i16, |value: i16| (value as u16) as u64);
1036impl_const_typed_unsigned_integer_format_traits!(u16, |value: u16| value as u64);
1037
1038impl Encode for bool {
1039    const ENCODED_SIZE_HINT: usize = 1;
1040
1041    #[inline(always)]
1042    fn encoded_size(&self) -> usize {
1043        1
1044    }
1045
1046    #[inline(always)]
1047    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
1048        unsafe {
1049            *buffer.add(*offset) = *self as u8;
1050        }
1051        *offset += 1;
1052    }
1053
1054    #[inline(always)]
1055    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
1056        unsafe {
1057            *buffer.add(offset) = *self as u8;
1058        }
1059    }
1060
1061    #[inline]
1062    unsafe fn decode_and_format(
1063        buffer: *const u8,
1064        offset: &mut usize,
1065        output: &mut Vec<u8>,
1066        format_spec: &str,
1067    ) {
1068        let value = unsafe { *buffer.add(*offset) } != 0;
1069        *offset += 1;
1070        if format_spec.is_empty() {
1071            number_format::append_bool(output, value);
1072        } else {
1073            append_display_with_spec(output, value, format_spec);
1074        }
1075    }
1076}
1077unsafe impl EncodeFast for bool {}
1078
1079impl Encode for f64 {
1080    const ENCODED_SIZE_HINT: usize = 8;
1081
1082    #[inline(always)]
1083    fn encoded_size(&self) -> usize {
1084        8
1085    }
1086
1087    #[inline(always)]
1088    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
1089        unsafe {
1090            buffer.add(*offset).cast::<f64>().write_unaligned(*self);
1091        }
1092        *offset += 8;
1093    }
1094
1095    #[inline(always)]
1096    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
1097        unsafe {
1098            buffer.add(offset).cast::<f64>().write_unaligned(*self);
1099        }
1100    }
1101
1102    #[inline]
1103    unsafe fn decode_and_format(
1104        buffer: *const u8,
1105        offset: &mut usize,
1106        output: &mut Vec<u8>,
1107        format_spec: &str,
1108    ) {
1109        let value = unsafe { buffer.add(*offset).cast::<f64>().read_unaligned() };
1110        *offset += 8;
1111        if format_spec.is_empty() {
1112            append_ryu_float(output, value);
1113        } else {
1114            append_float_with_spec(output, value, format_spec);
1115        }
1116    }
1117}
1118unsafe impl EncodeFast for f64 {}
1119
1120impl EncodeConstDefaultFormat for f64 {
1121    #[inline]
1122    unsafe fn decode_append_default_format<
1123        const FILL: u8,
1124        const ALIGN: u8,
1125        const WIDTH: usize,
1126        const PRECISION: usize,
1127        const ZERO_PAD: bool,
1128    >(
1129        buffer: *const u8,
1130        offset: &mut usize,
1131        output: &mut Vec<u8>,
1132    ) {
1133        let value = unsafe { buffer.add(*offset).cast::<f64>().read_unaligned() };
1134        *offset += 8;
1135        let mut body = Vec::new();
1136        if PRECISION == FORMAT_PRECISION_NONE {
1137            append_ryu_float(&mut body, value);
1138        } else {
1139            let mut writer = VecWriter(&mut body);
1140            write!(writer, "{:.*}", PRECISION, value).unwrap();
1141        }
1142        append_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, { FORMAT_ALIGN_RIGHT }>(output, &body);
1143    }
1144}
1145
1146impl EncodeConstFloatFormat for f64 {
1147    #[inline]
1148    unsafe fn decode_append_float_format<
1149        const FILL: u8,
1150        const ALIGN: u8,
1151        const WIDTH: usize,
1152        const PRECISION: usize,
1153        const ZERO_PAD: bool,
1154        const TY: u8,
1155    >(
1156        buffer: *const u8,
1157        offset: &mut usize,
1158        output: &mut Vec<u8>,
1159    ) {
1160        let value = unsafe { buffer.add(*offset).cast::<f64>().read_unaligned() };
1161        *offset += 8;
1162        let mut body = Vec::new();
1163        append_const_float_body::<f64, PRECISION, TY>(&mut body, value);
1164        append_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, { FORMAT_ALIGN_RIGHT }>(output, &body);
1165    }
1166}
1167
1168impl Encode for f32 {
1169    const ENCODED_SIZE_HINT: usize = 4;
1170
1171    #[inline(always)]
1172    fn encoded_size(&self) -> usize {
1173        4
1174    }
1175
1176    #[inline(always)]
1177    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize) {
1178        unsafe {
1179            buffer.add(*offset).cast::<f32>().write_unaligned(*self);
1180        }
1181        *offset += 4;
1182    }
1183
1184    #[inline(always)]
1185    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
1186        unsafe {
1187            buffer.add(offset).cast::<f32>().write_unaligned(*self);
1188        }
1189    }
1190
1191    #[inline]
1192    unsafe fn decode_and_format(
1193        buffer: *const u8,
1194        offset: &mut usize,
1195        output: &mut Vec<u8>,
1196        format_spec: &str,
1197    ) {
1198        let value = unsafe { buffer.add(*offset).cast::<f32>().read_unaligned() };
1199        *offset += 4;
1200        if format_spec.is_empty() {
1201            append_ryu_float(output, value);
1202        } else {
1203            append_float_with_spec(output, value, format_spec);
1204        }
1205    }
1206}
1207unsafe impl EncodeFast for f32 {}
1208
1209impl EncodeConstDefaultFormat for f32 {
1210    #[inline]
1211    unsafe fn decode_append_default_format<
1212        const FILL: u8,
1213        const ALIGN: u8,
1214        const WIDTH: usize,
1215        const PRECISION: usize,
1216        const ZERO_PAD: bool,
1217    >(
1218        buffer: *const u8,
1219        offset: &mut usize,
1220        output: &mut Vec<u8>,
1221    ) {
1222        let value = unsafe { buffer.add(*offset).cast::<f32>().read_unaligned() };
1223        *offset += 4;
1224        let mut body = Vec::new();
1225        if PRECISION == FORMAT_PRECISION_NONE {
1226            append_ryu_float(&mut body, value);
1227        } else {
1228            let mut writer = VecWriter(&mut body);
1229            write!(writer, "{:.*}", PRECISION, value).unwrap();
1230        }
1231        append_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, { FORMAT_ALIGN_RIGHT }>(output, &body);
1232    }
1233}
1234
1235impl EncodeConstFloatFormat for f32 {
1236    #[inline]
1237    unsafe fn decode_append_float_format<
1238        const FILL: u8,
1239        const ALIGN: u8,
1240        const WIDTH: usize,
1241        const PRECISION: usize,
1242        const ZERO_PAD: bool,
1243        const TY: u8,
1244    >(
1245        buffer: *const u8,
1246        offset: &mut usize,
1247        output: &mut Vec<u8>,
1248    ) {
1249        let value = unsafe { buffer.add(*offset).cast::<f32>().read_unaligned() };
1250        *offset += 4;
1251        let mut body = Vec::new();
1252        append_const_float_body::<f32, PRECISION, TY>(&mut body, value);
1253        append_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, { FORMAT_ALIGN_RIGHT }>(output, &body);
1254    }
1255}