const_panic/fmt/
fmt_compressed.rs

1use crate::fmt::{FmtArg, FmtKind, NumberFmt};
2
3/// A version of FmtArg which occupies less space, but needs to be unpacked to be used.
4#[derive(Copy, Clone)]
5#[cfg_attr(feature = "docsrs", doc(cfg(feature = "non_basic")))]
6pub struct PackedFmtArg {
7    indentation: u8,
8    bitfields: u8,
9}
10
11const FMT_KIND_OFFSET: u8 = 1;
12const NUMBER_FMT_OFFSET: u8 = FMT_KIND_OFFSET + FmtKind::BITS;
13
14impl FmtArg {
15    /// Converts this `FmtArg` into a `PackedFmtArg`,
16    /// which is smaller but can only be converted back into a `FmtArg`.
17    #[cfg_attr(feature = "docsrs", doc(cfg(feature = "non_basic")))]
18    pub const fn pack(self) -> PackedFmtArg {
19        let Self {
20            indentation,
21            is_alternate,
22            fmt_kind,
23            number_fmt,
24        } = self;
25
26        PackedFmtArg {
27            indentation,
28            bitfields: is_alternate as u8
29                | ((fmt_kind as u8) << FMT_KIND_OFFSET)
30                | ((number_fmt as u8) << NUMBER_FMT_OFFSET),
31        }
32    }
33}
34
35impl PackedFmtArg {
36    /// Converts this `PackedFmtArg` back into a `FmtArg`.
37    pub const fn unpack(self) -> FmtArg {
38        let indentation = self.indentation;
39        let is_alternate = (self.bitfields & 1) != 0;
40        let fmt_kind = FmtKind::from_prim(self.bitfields >> FMT_KIND_OFFSET);
41        let number_fmt = NumberFmt::from_prim(self.bitfields >> NUMBER_FMT_OFFSET);
42
43        FmtArg {
44            indentation,
45            is_alternate,
46            fmt_kind,
47            number_fmt,
48        }
49    }
50}
51
52macro_rules! enum_prim {
53    (
54        $type:ident, $bits:expr;
55        default $default:ident,
56        $($variant:ident),*
57        $(,)?
58    ) => (
59        #[allow(non_upper_case_globals)]
60        const _: () = {
61            $(const $variant: u8 = $type::$variant as u8;)*
62            const __MASK: u8 = 2u8.pow($bits) - 1;
63
64            match $type::$default {
65                $($type::$variant => (),)*
66                $type::$default => (),
67            }
68
69            impl $type {
70                #[allow(dead_code)]
71                const BITS: u8 = $bits;
72
73                const fn from_prim(n: u8) -> Self {
74                    match n & __MASK {
75                        $($variant => Self::$variant,)*
76                        _ => Self::$default,
77                    }
78                }
79            }
80        };
81    )
82}
83use enum_prim;
84
85enum_prim! {
86    FmtKind, 2;
87    default Debug,
88    Display,
89}
90
91enum_prim! {
92    NumberFmt, 2;
93    default Decimal,
94    Binary,
95    Hexadecimal,
96}