Skip to main content

ferrilog_core/encode/
traits.rs

1use super::{
2    Encode, FORMAT_ALIGN_LEFT, FORMAT_PRECISION_NONE,
3    format::{append_padded_const, write_const_format_spec},
4};
5
6pub trait EncodeLowerHex: Encode {
7    /// Decodes from `buffer + *offset` and appends the lowercase hex representation.
8    ///
9    /// # Safety
10    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
11    unsafe fn decode_append_lower_hex<const ALTERNATE: bool>(
12        buffer: *const u8,
13        offset: &mut usize,
14        output: &mut Vec<u8>,
15    );
16
17    /// Decodes from `buffer + offset` and appends lowercase hex.
18    ///
19    /// # Safety
20    /// `buffer + offset` must point to valid encoded data.
21    #[inline(always)]
22    unsafe fn decode_append_lower_hex_at_offset<const ALTERNATE: bool>(
23        buffer: *const u8,
24        offset: usize,
25        output: &mut Vec<u8>,
26    ) {
27        let mut offset = offset;
28        unsafe {
29            <Self as EncodeLowerHex>::decode_append_lower_hex::<ALTERNATE>(
30                buffer,
31                &mut offset,
32                output,
33            );
34        }
35    }
36}
37
38impl<T: Encode> EncodeLowerHex for T {
39    default unsafe fn decode_append_lower_hex<const ALTERNATE: bool>(
40        buffer: *const u8,
41        offset: &mut usize,
42        output: &mut Vec<u8>,
43    ) {
44        let format_spec = if ALTERNATE { ":#x" } else { ":x" };
45        unsafe {
46            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
47        }
48    }
49
50    #[inline(always)]
51    default unsafe fn decode_append_lower_hex_at_offset<const ALTERNATE: bool>(
52        buffer: *const u8,
53        offset: usize,
54        output: &mut Vec<u8>,
55    ) {
56        let mut offset = offset;
57        unsafe {
58            <T as EncodeLowerHex>::decode_append_lower_hex::<ALTERNATE>(
59                buffer,
60                &mut offset,
61                output,
62            );
63        }
64    }
65}
66
67pub trait EncodeUpperHex: Encode {
68    /// Decodes from `buffer + *offset` and appends the uppercase hex representation.
69    ///
70    /// # Safety
71    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
72    unsafe fn decode_append_upper_hex<const ALTERNATE: bool>(
73        buffer: *const u8,
74        offset: &mut usize,
75        output: &mut Vec<u8>,
76    );
77
78    /// Decodes from `buffer + offset` and appends uppercase hex.
79    ///
80    /// # Safety
81    /// `buffer + offset` must point to valid encoded data.
82    #[inline(always)]
83    unsafe fn decode_append_upper_hex_at_offset<const ALTERNATE: bool>(
84        buffer: *const u8,
85        offset: usize,
86        output: &mut Vec<u8>,
87    ) {
88        let mut offset = offset;
89        unsafe {
90            <Self as EncodeUpperHex>::decode_append_upper_hex::<ALTERNATE>(
91                buffer,
92                &mut offset,
93                output,
94            );
95        }
96    }
97}
98
99impl<T: Encode> EncodeUpperHex for T {
100    default unsafe fn decode_append_upper_hex<const ALTERNATE: bool>(
101        buffer: *const u8,
102        offset: &mut usize,
103        output: &mut Vec<u8>,
104    ) {
105        let format_spec = if ALTERNATE { ":#X" } else { ":X" };
106        unsafe {
107            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
108        }
109    }
110
111    #[inline(always)]
112    default unsafe fn decode_append_upper_hex_at_offset<const ALTERNATE: bool>(
113        buffer: *const u8,
114        offset: usize,
115        output: &mut Vec<u8>,
116    ) {
117        let mut offset = offset;
118        unsafe {
119            <T as EncodeUpperHex>::decode_append_upper_hex::<ALTERNATE>(
120                buffer,
121                &mut offset,
122                output,
123            );
124        }
125    }
126}
127
128pub trait EncodeBinary: Encode {
129    /// Decodes from `buffer + *offset` and appends the binary representation.
130    ///
131    /// # Safety
132    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
133    unsafe fn decode_append_binary<const ALTERNATE: bool>(
134        buffer: *const u8,
135        offset: &mut usize,
136        output: &mut Vec<u8>,
137    );
138
139    /// Decodes from `buffer + offset` and appends binary.
140    ///
141    /// # Safety
142    /// `buffer + offset` must point to valid encoded data.
143    #[inline(always)]
144    unsafe fn decode_append_binary_at_offset<const ALTERNATE: bool>(
145        buffer: *const u8,
146        offset: usize,
147        output: &mut Vec<u8>,
148    ) {
149        let mut offset = offset;
150        unsafe {
151            <Self as EncodeBinary>::decode_append_binary::<ALTERNATE>(buffer, &mut offset, output);
152        }
153    }
154}
155
156impl<T: Encode> EncodeBinary for T {
157    default unsafe fn decode_append_binary<const ALTERNATE: bool>(
158        buffer: *const u8,
159        offset: &mut usize,
160        output: &mut Vec<u8>,
161    ) {
162        let format_spec = if ALTERNATE { ":#b" } else { ":b" };
163        unsafe {
164            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
165        }
166    }
167
168    #[inline(always)]
169    default unsafe fn decode_append_binary_at_offset<const ALTERNATE: bool>(
170        buffer: *const u8,
171        offset: usize,
172        output: &mut Vec<u8>,
173    ) {
174        let mut offset = offset;
175        unsafe {
176            <T as EncodeBinary>::decode_append_binary::<ALTERNATE>(buffer, &mut offset, output);
177        }
178    }
179}
180
181pub trait EncodeOctal: Encode {
182    /// Decodes from `buffer + *offset` and appends the octal representation.
183    ///
184    /// # Safety
185    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
186    unsafe fn decode_append_octal<const ALTERNATE: bool>(
187        buffer: *const u8,
188        offset: &mut usize,
189        output: &mut Vec<u8>,
190    );
191
192    /// Decodes from `buffer + offset` and appends octal.
193    ///
194    /// # Safety
195    /// `buffer + offset` must point to valid encoded data.
196    #[inline(always)]
197    unsafe fn decode_append_octal_at_offset<const ALTERNATE: bool>(
198        buffer: *const u8,
199        offset: usize,
200        output: &mut Vec<u8>,
201    ) {
202        let mut offset = offset;
203        unsafe {
204            <Self as EncodeOctal>::decode_append_octal::<ALTERNATE>(buffer, &mut offset, output);
205        }
206    }
207}
208
209impl<T: Encode> EncodeOctal for T {
210    default unsafe fn decode_append_octal<const ALTERNATE: bool>(
211        buffer: *const u8,
212        offset: &mut usize,
213        output: &mut Vec<u8>,
214    ) {
215        let format_spec = if ALTERNATE { ":#o" } else { ":o" };
216        unsafe {
217            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
218        }
219    }
220
221    #[inline(always)]
222    default unsafe fn decode_append_octal_at_offset<const ALTERNATE: bool>(
223        buffer: *const u8,
224        offset: usize,
225        output: &mut Vec<u8>,
226    ) {
227        let mut offset = offset;
228        unsafe {
229            <T as EncodeOctal>::decode_append_octal::<ALTERNATE>(buffer, &mut offset, output);
230        }
231    }
232}
233
234pub trait EncodeConstDefaultFormat: Encode {
235    /// Decodes from `buffer + *offset` and appends the value with compile-time formatting.
236    ///
237    /// # Safety
238    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
239    unsafe fn decode_append_default_format<
240        const FILL: u8,
241        const ALIGN: u8,
242        const WIDTH: usize,
243        const PRECISION: usize,
244        const ZERO_PAD: bool,
245    >(
246        buffer: *const u8,
247        offset: &mut usize,
248        output: &mut Vec<u8>,
249    );
250
251    /// Decodes from `buffer + offset` and appends the value with compile-time formatting.
252    ///
253    /// # Safety
254    /// `buffer + offset` must point to valid encoded data.
255    #[inline(always)]
256    unsafe fn decode_append_default_format_at_offset<
257        const FILL: u8,
258        const ALIGN: u8,
259        const WIDTH: usize,
260        const PRECISION: usize,
261        const ZERO_PAD: bool,
262    >(
263        buffer: *const u8,
264        offset: usize,
265        output: &mut Vec<u8>,
266    ) {
267        let mut offset = offset;
268        unsafe {
269            <Self as EncodeConstDefaultFormat>::decode_append_default_format::<
270                FILL,
271                ALIGN,
272                WIDTH,
273                PRECISION,
274                ZERO_PAD,
275            >(buffer, &mut offset, output);
276        }
277    }
278}
279
280impl<T: Encode> EncodeConstDefaultFormat for T {
281    default unsafe fn decode_append_default_format<
282        const FILL: u8,
283        const ALIGN: u8,
284        const WIDTH: usize,
285        const PRECISION: usize,
286        const ZERO_PAD: bool,
287    >(
288        buffer: *const u8,
289        offset: &mut usize,
290        output: &mut Vec<u8>,
291    ) {
292        let mut body = Vec::new();
293        unsafe {
294            <T as Encode>::decode_and_format(buffer, offset, &mut body, "");
295        }
296        if PRECISION != FORMAT_PRECISION_NONE && body.len() > PRECISION {
297            body.truncate(PRECISION);
298        }
299        append_padded_const::<FILL, ALIGN, WIDTH, ZERO_PAD, { FORMAT_ALIGN_LEFT }>(output, &body);
300    }
301
302    #[inline(always)]
303    default unsafe fn decode_append_default_format_at_offset<
304        const FILL: u8,
305        const ALIGN: u8,
306        const WIDTH: usize,
307        const PRECISION: usize,
308        const ZERO_PAD: bool,
309    >(
310        buffer: *const u8,
311        offset: usize,
312        output: &mut Vec<u8>,
313    ) {
314        let mut offset = offset;
315        unsafe {
316            <T as EncodeConstDefaultFormat>::decode_append_default_format::<
317                FILL,
318                ALIGN,
319                WIDTH,
320                PRECISION,
321                ZERO_PAD,
322            >(buffer, &mut offset, output);
323        }
324    }
325}
326
327pub trait EncodeConstLowerHexFormat: Encode {
328    /// Decodes from `buffer + *offset` and appends formatted lowercase hex.
329    ///
330    /// # Safety
331    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
332    unsafe fn decode_append_lower_hex_format<
333        const FILL: u8,
334        const ALIGN: u8,
335        const WIDTH: usize,
336        const ZERO_PAD: bool,
337        const ALTERNATE: bool,
338    >(
339        buffer: *const u8,
340        offset: &mut usize,
341        output: &mut Vec<u8>,
342    );
343
344    /// Decodes from `buffer + offset` and appends formatted lowercase hex.
345    ///
346    /// # Safety
347    /// `buffer + offset` must point to valid encoded data.
348    #[inline(always)]
349    unsafe fn decode_append_lower_hex_format_at_offset<
350        const FILL: u8,
351        const ALIGN: u8,
352        const WIDTH: usize,
353        const ZERO_PAD: bool,
354        const ALTERNATE: bool,
355    >(
356        buffer: *const u8,
357        offset: usize,
358        output: &mut Vec<u8>,
359    ) {
360        let mut offset = offset;
361        unsafe {
362            <Self as EncodeConstLowerHexFormat>::decode_append_lower_hex_format::<
363                FILL,
364                ALIGN,
365                WIDTH,
366                ZERO_PAD,
367                ALTERNATE,
368            >(buffer, &mut offset, output);
369        }
370    }
371}
372
373impl<T: Encode> EncodeConstLowerHexFormat for T {
374    default unsafe fn decode_append_lower_hex_format<
375        const FILL: u8,
376        const ALIGN: u8,
377        const WIDTH: usize,
378        const ZERO_PAD: bool,
379        const ALTERNATE: bool,
380    >(
381        buffer: *const u8,
382        offset: &mut usize,
383        output: &mut Vec<u8>,
384    ) {
385        let mut format_spec = [0u8; 32];
386        let length = write_const_format_spec::<
387            FILL,
388            ALIGN,
389            WIDTH,
390            FORMAT_PRECISION_NONE,
391            ZERO_PAD,
392            ALTERNATE,
393            b'x',
394        >(&mut format_spec);
395        let format_spec = unsafe { std::str::from_utf8_unchecked(&format_spec[..length]) };
396        unsafe {
397            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
398        }
399    }
400
401    #[inline(always)]
402    default unsafe fn decode_append_lower_hex_format_at_offset<
403        const FILL: u8,
404        const ALIGN: u8,
405        const WIDTH: usize,
406        const ZERO_PAD: bool,
407        const ALTERNATE: bool,
408    >(
409        buffer: *const u8,
410        offset: usize,
411        output: &mut Vec<u8>,
412    ) {
413        let mut offset = offset;
414        unsafe {
415            <T as EncodeConstLowerHexFormat>::decode_append_lower_hex_format::<
416                FILL,
417                ALIGN,
418                WIDTH,
419                ZERO_PAD,
420                ALTERNATE,
421            >(buffer, &mut offset, output);
422        }
423    }
424}
425
426pub trait EncodeConstUpperHexFormat: Encode {
427    /// Decodes from `buffer + *offset` and appends formatted uppercase hex.
428    ///
429    /// # Safety
430    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
431    unsafe fn decode_append_upper_hex_format<
432        const FILL: u8,
433        const ALIGN: u8,
434        const WIDTH: usize,
435        const ZERO_PAD: bool,
436        const ALTERNATE: bool,
437    >(
438        buffer: *const u8,
439        offset: &mut usize,
440        output: &mut Vec<u8>,
441    );
442
443    /// Decodes from `buffer + offset` and appends formatted uppercase hex.
444    ///
445    /// # Safety
446    /// `buffer + offset` must point to valid encoded data.
447    #[inline(always)]
448    unsafe fn decode_append_upper_hex_format_at_offset<
449        const FILL: u8,
450        const ALIGN: u8,
451        const WIDTH: usize,
452        const ZERO_PAD: bool,
453        const ALTERNATE: bool,
454    >(
455        buffer: *const u8,
456        offset: usize,
457        output: &mut Vec<u8>,
458    ) {
459        let mut offset = offset;
460        unsafe {
461            <Self as EncodeConstUpperHexFormat>::decode_append_upper_hex_format::<
462                FILL,
463                ALIGN,
464                WIDTH,
465                ZERO_PAD,
466                ALTERNATE,
467            >(buffer, &mut offset, output);
468        }
469    }
470}
471
472impl<T: Encode> EncodeConstUpperHexFormat for T {
473    default unsafe fn decode_append_upper_hex_format<
474        const FILL: u8,
475        const ALIGN: u8,
476        const WIDTH: usize,
477        const ZERO_PAD: bool,
478        const ALTERNATE: bool,
479    >(
480        buffer: *const u8,
481        offset: &mut usize,
482        output: &mut Vec<u8>,
483    ) {
484        let mut format_spec = [0u8; 32];
485        let length = write_const_format_spec::<
486            FILL,
487            ALIGN,
488            WIDTH,
489            FORMAT_PRECISION_NONE,
490            ZERO_PAD,
491            ALTERNATE,
492            b'X',
493        >(&mut format_spec);
494        let format_spec = unsafe { std::str::from_utf8_unchecked(&format_spec[..length]) };
495        unsafe {
496            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
497        }
498    }
499
500    #[inline(always)]
501    default unsafe fn decode_append_upper_hex_format_at_offset<
502        const FILL: u8,
503        const ALIGN: u8,
504        const WIDTH: usize,
505        const ZERO_PAD: bool,
506        const ALTERNATE: bool,
507    >(
508        buffer: *const u8,
509        offset: usize,
510        output: &mut Vec<u8>,
511    ) {
512        let mut offset = offset;
513        unsafe {
514            <T as EncodeConstUpperHexFormat>::decode_append_upper_hex_format::<
515                FILL,
516                ALIGN,
517                WIDTH,
518                ZERO_PAD,
519                ALTERNATE,
520            >(buffer, &mut offset, output);
521        }
522    }
523}
524
525pub trait EncodeConstBinaryFormat: Encode {
526    /// Decodes from `buffer + *offset` and appends formatted binary.
527    ///
528    /// # Safety
529    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
530    unsafe fn decode_append_binary_format<
531        const FILL: u8,
532        const ALIGN: u8,
533        const WIDTH: usize,
534        const ZERO_PAD: bool,
535        const ALTERNATE: bool,
536    >(
537        buffer: *const u8,
538        offset: &mut usize,
539        output: &mut Vec<u8>,
540    );
541
542    /// Decodes from `buffer + offset` and appends formatted binary.
543    ///
544    /// # Safety
545    /// `buffer + offset` must point to valid encoded data.
546    #[inline(always)]
547    unsafe fn decode_append_binary_format_at_offset<
548        const FILL: u8,
549        const ALIGN: u8,
550        const WIDTH: usize,
551        const ZERO_PAD: bool,
552        const ALTERNATE: bool,
553    >(
554        buffer: *const u8,
555        offset: usize,
556        output: &mut Vec<u8>,
557    ) {
558        let mut offset = offset;
559        unsafe {
560            <Self as EncodeConstBinaryFormat>::decode_append_binary_format::<
561                FILL,
562                ALIGN,
563                WIDTH,
564                ZERO_PAD,
565                ALTERNATE,
566            >(buffer, &mut offset, output);
567        }
568    }
569}
570
571impl<T: Encode> EncodeConstBinaryFormat for T {
572    default unsafe fn decode_append_binary_format<
573        const FILL: u8,
574        const ALIGN: u8,
575        const WIDTH: usize,
576        const ZERO_PAD: bool,
577        const ALTERNATE: bool,
578    >(
579        buffer: *const u8,
580        offset: &mut usize,
581        output: &mut Vec<u8>,
582    ) {
583        let mut format_spec = [0u8; 32];
584        let length = write_const_format_spec::<
585            FILL,
586            ALIGN,
587            WIDTH,
588            FORMAT_PRECISION_NONE,
589            ZERO_PAD,
590            ALTERNATE,
591            b'b',
592        >(&mut format_spec);
593        let format_spec = unsafe { std::str::from_utf8_unchecked(&format_spec[..length]) };
594        unsafe {
595            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
596        }
597    }
598
599    #[inline(always)]
600    default unsafe fn decode_append_binary_format_at_offset<
601        const FILL: u8,
602        const ALIGN: u8,
603        const WIDTH: usize,
604        const ZERO_PAD: bool,
605        const ALTERNATE: bool,
606    >(
607        buffer: *const u8,
608        offset: usize,
609        output: &mut Vec<u8>,
610    ) {
611        let mut offset = offset;
612        unsafe {
613            <T as EncodeConstBinaryFormat>::decode_append_binary_format::<
614                FILL,
615                ALIGN,
616                WIDTH,
617                ZERO_PAD,
618                ALTERNATE,
619            >(buffer, &mut offset, output);
620        }
621    }
622}
623
624pub trait EncodeConstOctalFormat: Encode {
625    /// Decodes from `buffer + *offset` and appends formatted octal.
626    ///
627    /// # Safety
628    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
629    unsafe fn decode_append_octal_format<
630        const FILL: u8,
631        const ALIGN: u8,
632        const WIDTH: usize,
633        const ZERO_PAD: bool,
634        const ALTERNATE: bool,
635    >(
636        buffer: *const u8,
637        offset: &mut usize,
638        output: &mut Vec<u8>,
639    );
640
641    /// Decodes from `buffer + offset` and appends formatted octal.
642    ///
643    /// # Safety
644    /// `buffer + offset` must point to valid encoded data.
645    #[inline(always)]
646    unsafe fn decode_append_octal_format_at_offset<
647        const FILL: u8,
648        const ALIGN: u8,
649        const WIDTH: usize,
650        const ZERO_PAD: bool,
651        const ALTERNATE: bool,
652    >(
653        buffer: *const u8,
654        offset: usize,
655        output: &mut Vec<u8>,
656    ) {
657        let mut offset = offset;
658        unsafe {
659            <Self as EncodeConstOctalFormat>::decode_append_octal_format::<
660                FILL,
661                ALIGN,
662                WIDTH,
663                ZERO_PAD,
664                ALTERNATE,
665            >(buffer, &mut offset, output);
666        }
667    }
668}
669
670impl<T: Encode> EncodeConstOctalFormat for T {
671    default unsafe fn decode_append_octal_format<
672        const FILL: u8,
673        const ALIGN: u8,
674        const WIDTH: usize,
675        const ZERO_PAD: bool,
676        const ALTERNATE: bool,
677    >(
678        buffer: *const u8,
679        offset: &mut usize,
680        output: &mut Vec<u8>,
681    ) {
682        let mut format_spec = [0u8; 32];
683        let length = write_const_format_spec::<
684            FILL,
685            ALIGN,
686            WIDTH,
687            FORMAT_PRECISION_NONE,
688            ZERO_PAD,
689            ALTERNATE,
690            b'o',
691        >(&mut format_spec);
692        let format_spec = unsafe { std::str::from_utf8_unchecked(&format_spec[..length]) };
693        unsafe {
694            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
695        }
696    }
697
698    #[inline(always)]
699    default unsafe fn decode_append_octal_format_at_offset<
700        const FILL: u8,
701        const ALIGN: u8,
702        const WIDTH: usize,
703        const ZERO_PAD: bool,
704        const ALTERNATE: bool,
705    >(
706        buffer: *const u8,
707        offset: usize,
708        output: &mut Vec<u8>,
709    ) {
710        let mut offset = offset;
711        unsafe {
712            <T as EncodeConstOctalFormat>::decode_append_octal_format::<
713                FILL,
714                ALIGN,
715                WIDTH,
716                ZERO_PAD,
717                ALTERNATE,
718            >(buffer, &mut offset, output);
719        }
720    }
721}
722
723pub trait EncodeConstFloatFormat: Encode {
724    /// Decodes from `buffer + *offset` and appends formatted float.
725    ///
726    /// # Safety
727    /// `buffer + *offset` must point to valid encoded data written by [`Encode::encode`].
728    unsafe fn decode_append_float_format<
729        const FILL: u8,
730        const ALIGN: u8,
731        const WIDTH: usize,
732        const PRECISION: usize,
733        const ZERO_PAD: bool,
734        const TY: u8,
735    >(
736        buffer: *const u8,
737        offset: &mut usize,
738        output: &mut Vec<u8>,
739    );
740
741    /// Decodes from `buffer + offset` and appends formatted float.
742    ///
743    /// # Safety
744    /// `buffer + offset` must point to valid encoded data.
745    #[inline(always)]
746    unsafe fn decode_append_float_format_at_offset<
747        const FILL: u8,
748        const ALIGN: u8,
749        const WIDTH: usize,
750        const PRECISION: usize,
751        const ZERO_PAD: bool,
752        const TY: u8,
753    >(
754        buffer: *const u8,
755        offset: usize,
756        output: &mut Vec<u8>,
757    ) {
758        let mut offset = offset;
759        unsafe {
760            <Self as EncodeConstFloatFormat>::decode_append_float_format::<
761                FILL,
762                ALIGN,
763                WIDTH,
764                PRECISION,
765                ZERO_PAD,
766                TY,
767            >(buffer, &mut offset, output);
768        }
769    }
770}
771
772impl<T: Encode> EncodeConstFloatFormat for T {
773    default unsafe fn decode_append_float_format<
774        const FILL: u8,
775        const ALIGN: u8,
776        const WIDTH: usize,
777        const PRECISION: usize,
778        const ZERO_PAD: bool,
779        const TY: u8,
780    >(
781        buffer: *const u8,
782        offset: &mut usize,
783        output: &mut Vec<u8>,
784    ) {
785        let mut format_spec = [0u8; 32];
786        let length = write_const_format_spec::<FILL, ALIGN, WIDTH, PRECISION, ZERO_PAD, false, TY>(
787            &mut format_spec,
788        );
789        let format_spec = unsafe { std::str::from_utf8_unchecked(&format_spec[..length]) };
790        unsafe {
791            <T as Encode>::decode_and_format(buffer, offset, output, format_spec);
792        }
793    }
794
795    #[inline(always)]
796    default unsafe fn decode_append_float_format_at_offset<
797        const FILL: u8,
798        const ALIGN: u8,
799        const WIDTH: usize,
800        const PRECISION: usize,
801        const ZERO_PAD: bool,
802        const TY: u8,
803    >(
804        buffer: *const u8,
805        offset: usize,
806        output: &mut Vec<u8>,
807    ) {
808        let mut offset = offset;
809        unsafe {
810            <T as EncodeConstFloatFormat>::decode_append_float_format::<
811                FILL,
812                ALIGN,
813                WIDTH,
814                PRECISION,
815                ZERO_PAD,
816                TY,
817            >(buffer, &mut offset, output);
818        }
819    }
820}