kdk_entropy/error.rs
1use core::fmt;
2
3/// Errors returned by [`crate::dice_to_entropy`] and friends.
4///
5/// Manual `Display` (no `thiserror`) so the error messages stay auditable
6/// and don't accidentally inherit upstream formatting that could leak
7/// secret bytes.
8#[derive(Debug, PartialEq, Eq)]
9pub enum EntropyError {
10 /// Caller supplied fewer rolls than `min_rolls::<FACES, N>()` requires.
11 /// Fields: `(required, given)`.
12 TooFewRolls(usize, usize),
13
14 /// Caller supplied more rolls than `max_rolls::<FACES, N>()` permits.
15 /// Fields: `(allowed, given)`.
16 TooManyRolls(usize, usize),
17
18 /// A roll byte was outside the valid range `1..=FACES`.
19 /// Fields: `(value, index)`.
20 RollOutOfRange(u8, usize),
21
22 /// The `(FACES, N)` generic combination is not one of the supported
23 /// dice configurations (d6/d20 × 16/32 bytes). Fields: `(FACES, N)`.
24 UnsupportedConfig(u8, usize),
25
26 /// A card byte appeared twice in the input — only relevant to
27 /// `deck_to_entropy`. Fields: `(value, second_index)`.
28 DuplicateCard(u8, usize),
29}
30
31impl fmt::Display for EntropyError {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 EntropyError::TooFewRolls(required, given) => {
35 write!(f, "too few rolls: required {required}, got {given}")
36 }
37 EntropyError::TooManyRolls(allowed, given) => {
38 write!(
39 f,
40 "too many rolls: at most {allowed} permitted, got {given}"
41 )
42 }
43 EntropyError::RollOutOfRange(value, index) => {
44 write!(
45 f,
46 "roll at index {index} has value {value}: out of valid range"
47 )
48 }
49 EntropyError::UnsupportedConfig(faces, n) => {
50 write!(
51 f,
52 "unsupported (FACES, N) configuration: ({faces}, {n}) — supported: d6/d20 x 16/32 bytes"
53 )
54 }
55 EntropyError::DuplicateCard(value, index) => {
56 write!(f, "card value {value} at index {index} was already drawn")
57 }
58 }
59 }
60}
61
62impl core::error::Error for EntropyError {}