weiss_core/
error.rs

1use thiserror::Error;
2
3use crate::db::CardId;
4
5/// Stable error categories for environment configuration validation.
6#[derive(Clone, Copy, Debug, Error, PartialEq, Eq)]
7pub enum ConfigError {
8    /// A player's deck length did not match the expected size.
9    #[error("deck length invalid for player {player}: got {got}, expected {expected}")]
10    DeckLength {
11        /// Player index.
12        player: u8,
13        /// Observed deck length.
14        got: usize,
15        /// Expected deck length.
16        expected: usize,
17    },
18    /// A player's deck referenced a card id that is not present in the database.
19    #[error("unknown card id {card_id} in player {player} deck")]
20    UnknownCardId {
21        /// Player index.
22        player: u8,
23        /// Unknown card id.
24        card_id: CardId,
25    },
26    /// A player's deck contained too many climax cards.
27    #[error("too many climax cards for player {player}: got {got}, max {max}")]
28    ClimaxCount {
29        /// Player index.
30        player: u8,
31        /// Observed climax count.
32        got: usize,
33        /// Maximum allowed climax count.
34        max: usize,
35    },
36    /// A player's deck contained too many copies of a single card id.
37    #[error("too many copies of card {card_id} for player {player}: got {got}, max {max}")]
38    CardCopyCount {
39        /// Player index.
40        player: u8,
41        /// Card id with excessive copies.
42        card_id: CardId,
43        /// Observed copy count.
44        got: usize,
45        /// Maximum allowed copies.
46        max: usize,
47    },
48}
49
50/// Stable error categories for game-state construction.
51#[derive(Clone, Copy, Debug, Error, PartialEq, Eq)]
52pub enum StateError {
53    /// Starting player must be either player 0 or player 1.
54    #[error("starting player must be 0 or 1 (got {got})")]
55    InvalidStartingPlayer {
56        /// Provided starting player index.
57        got: u8,
58    },
59    /// A player's deck length did not match the expected size for state construction.
60    #[error("deck length invalid for owner {owner}: got {got}, expected {expected}")]
61    DeckLength {
62        /// Player index.
63        owner: u8,
64        /// Observed deck length.
65        got: usize,
66        /// Expected deck length.
67        expected: usize,
68    },
69}
70
71/// Stable error categories for action application.
72#[derive(Clone, Copy, Debug, Error, PartialEq, Eq)]
73pub enum ActionError {
74    /// An action was attempted when no decision is pending.
75    #[error("no pending decision")]
76    NoPendingDecision,
77    /// An action id could not be decoded or is outside the action space.
78    #[error("invalid action id {action_id}")]
79    InvalidActionId {
80        /// Provided action id.
81        action_id: usize,
82    },
83    /// An action id was decoded but is not legal for the current decision.
84    #[error("action is not legal for current decision")]
85    ActionNotLegal,
86}
87
88/// Stable error categories for runtime invariant violations.
89#[derive(Clone, Copy, Debug, Error, PartialEq, Eq)]
90pub enum InvariantError {
91    /// Internal choice paging index exceeded the available options.
92    #[error("choice paging index out of range: {index}")]
93    ChoicePagingIndexOutOfRange {
94        /// Provided choice paging index.
95        index: usize,
96    },
97    /// Trigger id counter overflowed its representable range.
98    #[error("trigger id overflow")]
99    TriggerIdOverflow,
100    /// Action mask bit buffer size did not match the expected capacity.
101    #[error("mask bits buffer size mismatch")]
102    MaskBitsBufferSizeMismatch,
103    /// A computed action id exceeded `u16::MAX`.
104    #[error("action id out of u16 range: {id}")]
105    ActionIdOutOfU16Range {
106        /// Computed action id.
107        id: usize,
108    },
109    /// A generic stage mover received an invalid stage zone target.
110    #[error("invalid stage zone target for generic zone mover")]
111    InvalidStageZoneTarget,
112    /// Fingerprint serialization failed unexpectedly.
113    #[error("fingerprint serialization failed")]
114    FingerprintSerializationFailed,
115}
116
117/// Top-level environment construction errors.
118#[derive(Debug, Error)]
119pub enum EnvError {
120    /// Environment configuration validation failed.
121    #[error(transparent)]
122    Config(#[from] ConfigError),
123    /// Initial game-state construction failed.
124    #[error(transparent)]
125    State(#[from] StateError),
126    /// The initial reset trapped a fault and returned a status code.
127    #[error("initial reset faulted with engine status code {code}")]
128    InitialResetFault {
129        /// Engine error code returned by reset.
130        code: u8,
131    },
132}