1#![allow(clippy::unusual_byte_groupings)]
4
5use core::fmt;
6use core::mem;
7
8use musli::{Decode, Decoder};
9
10#[derive(Debug)]
12#[repr(u8)]
13pub enum Mark {
14 None = 0b000,
16 Some = 0b001,
18 True = 0b011,
20 False = 0b010,
22 Variant = 0b100,
24 Char = 0b101,
26 Unit = 0b110,
28 Reserved0 = 0b111,
30}
31
32#[derive(Debug, Clone, Copy)]
37#[repr(u8)]
38pub(crate) enum NumberKind {
39 Signed = 0b00,
41 Unsigned = 0b01,
43 Float = 0b10,
45 #[allow(unused)]
47 Reserved0 = 0b11,
48}
49
50#[repr(u8)]
55pub(crate) enum Width {
56 #[allow(unused)]
57 Reserved0 = 0b000,
58 #[allow(unused)]
59 Reserved1 = 0b001,
60 #[allow(unused)]
61 Reserved2 = 0b010,
62 U8 = 0b011,
64 U16 = 0b100,
66 U32 = 0b101,
68 U64 = 0b110,
70 U128 = 0b111,
72}
73
74#[test]
75fn ensure_width() {
76 assert_eq!(2u32.pow(Width::U8 as u32), 8u32);
77 assert_eq!(1u32 << Width::U8 as u32, 8u32);
78 assert_eq!(2u32.pow(Width::U16 as u32), 16u32);
79 assert_eq!(1u32 << Width::U16 as u32, 16u32);
80 assert_eq!(2u32.pow(Width::U32 as u32), 32u32);
81 assert_eq!(1u32 << Width::U32 as u32, 32u32);
82 assert_eq!(2u32.pow(Width::U64 as u32), 64u32);
83 assert_eq!(1u32 << Width::U64 as u32, 64u32);
84 assert_eq!(2u32.pow(Width::U128 as u32), 128u32);
85 assert_eq!(1u32 << Width::U128 as u32, 128u32);
86}
87
88pub const U8: u8 = (Width::U8 as u8) << 2 | NumberKind::Unsigned as u8;
90pub const U16: u8 = (Width::U16 as u8) << 2 | NumberKind::Unsigned as u8;
92pub const U32: u8 = (Width::U32 as u8) << 2 | NumberKind::Unsigned as u8;
94pub const U64: u8 = (Width::U64 as u8) << 2 | NumberKind::Unsigned as u8;
96pub const U128: u8 = (Width::U128 as u8) << 2 | NumberKind::Unsigned as u8;
98pub const I8: u8 = (Width::U8 as u8) << 2 | NumberKind::Signed as u8;
100pub const I16: u8 = (Width::U16 as u8) << 2 | NumberKind::Signed as u8;
102pub const I32: u8 = (Width::U32 as u8) << 2 | NumberKind::Signed as u8;
104pub const I64: u8 = (Width::U64 as u8) << 2 | NumberKind::Signed as u8;
106pub const I128: u8 = (Width::U128 as u8) << 2 | NumberKind::Signed as u8;
108pub const F32: u8 = (Width::U32 as u8) << 2 | NumberKind::Float as u8;
110pub const F64: u8 = (Width::U64 as u8) << 2 | NumberKind::Float as u8;
112#[cfg(target_pointer_width = "32")]
114pub const USIZE: u8 = U32;
115#[cfg(target_pointer_width = "64")]
117pub const USIZE: u8 = U64;
118#[cfg(target_pointer_width = "32")]
120pub const ISIZE: u8 = I32;
121#[cfg(target_pointer_width = "64")]
123pub const ISIZE: u8 = I64;
124
125pub(crate) const DATA_MASK: u8 = 0b000_11111;
127pub(crate) const MARK_MASK: u8 = 0b00000_111;
128pub(crate) const NUMBER_KIND_MASK: u8 = 0b000000_11;
129pub const MAX_INLINE_LEN: usize = (DATA_MASK - 1) as usize;
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
135#[repr(u8)]
136pub enum Kind {
137 Reserved0 = 0b000_00000,
139 Reserved1 = 0b001_00000,
141 Number = 0b010_00000,
143 Sequence = 0b011_00000,
145 Map = 0b100_00000,
147 Bytes = 0b101_00000,
149 String = 0b110_00000,
151 Mark = 0b111_00000,
153}
154
155#[derive(Clone, Copy, PartialEq, Eq, Hash)]
162#[repr(transparent)]
163pub struct Tag {
164 repr: u8,
166}
167
168impl Tag {
169 #[inline]
174 pub const fn new(kind: Kind, data: u8) -> Self {
175 Self {
176 repr: kind as u8 | data,
177 }
178 }
179
180 #[inline]
182 pub const fn from_mark(mark: Mark) -> Self {
183 Self {
184 repr: Kind::Mark as u8 | mark as u8,
185 }
186 }
187
188 #[inline]
190 pub const fn mark(&self) -> Mark {
191 unsafe { mem::transmute(self.repr & MARK_MASK) }
194 }
195
196 #[inline]
198 pub(crate) const fn number_kind(&self) -> NumberKind {
199 unsafe { mem::transmute(self.repr & NUMBER_KIND_MASK) }
202 }
203
204 #[inline]
206 pub const fn empty(kind: Kind) -> Self {
207 Self {
208 repr: kind as u8 | DATA_MASK,
209 }
210 }
211
212 #[inline]
214 pub const fn from_byte(repr: u8) -> Self {
215 Self { repr }
216 }
217
218 #[inline]
220 pub const fn byte(self) -> u8 {
221 self.repr
222 }
223
224 #[inline]
226 pub const fn kind(self) -> Kind {
227 unsafe { mem::transmute(self.repr & !DATA_MASK) }
230 }
231
232 #[inline]
235 pub(crate) const fn data_raw(self) -> u8 {
236 self.repr & DATA_MASK
237 }
238
239 #[inline]
242 pub const fn data(self) -> Option<u8> {
243 let data = self.data_raw();
244
245 if data == DATA_MASK {
246 None
247 } else {
248 Some(data)
249 }
250 }
251
252 #[inline]
257 pub const fn with_len(kind: Kind, len: usize) -> (Self, bool) {
258 if len < DATA_MASK as usize {
259 (Self::new(kind, len as u8), true)
260 } else {
261 (Self::new(kind, DATA_MASK), false)
262 }
263 }
264
265 #[inline]
270 pub const fn with_byte(kind: Kind, len: u8) -> (Self, bool) {
271 if len < DATA_MASK {
272 (Self::new(kind, len), true)
273 } else {
274 (Self::new(kind, DATA_MASK), false)
275 }
276 }
277}
278
279impl fmt::Debug for Tag {
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 f.debug_struct("Tag")
282 .field("kind", &self.kind())
283 .field("data", &self.data())
284 .finish()
285 }
286}
287
288impl<'de, M> Decode<'de, M> for Tag {
289 #[inline]
290 fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
291 where
292 D: Decoder<'de, Mode = M>,
293 {
294 Ok(Self::from_byte(decoder.decode_u8()?))
295 }
296}