1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use crateDecodeError;
/// A type that can be packed into a mixed-radix representation.
///
/// Each implementor declares how many distinct values it can take ([`RADIX`](Self::RADIX))
/// and provides bidirectional mapping between values and ordinals in `[0, RADIX)`.
///
/// Planck uses these ordinals to encode structs as mixed-radix numbers: each field
/// becomes a digit with its own base. The total number of bits needed is
/// `⌈log₂(r₁ × r₂ × ... × rₙ)⌉`, which is always ≤ the sum of individual field bit widths.
///
/// # Derive
///
/// The easiest way to implement this trait is via `#[derive(Planck)]` from the `planck` crate.
///
/// # Manual Implementation
///
/// ```
/// use planck_pack_core::{Packable, DecodeError};
///
/// struct DieRoll(u8); // 1-6
///
/// impl Packable for DieRoll {
/// const RADIX: u128 = 6;
///
/// fn to_ordinal(&self) -> u128 {
/// (self.0 - 1) as u128
/// }
///
/// fn from_ordinal(ord: u128) -> Result<Self, DecodeError> {
/// if ord < 6 {
/// Ok(DieRoll(ord as u8 + 1))
/// } else {
/// Err(DecodeError::OrdinalOutOfRange { ordinal: ord, radix: 6 })
/// }
/// }
/// }
///
/// assert_eq!(DieRoll(3).to_ordinal(), 2);
/// assert_eq!(DieRoll::RADIX, 6);
/// ```