Skip to main content

subtr_actor/domain/
error.rs

1use crate::*;
2use std::backtrace::Backtrace;
3use thiserror::Error;
4
5/// [`SubtrActorErrorVariant`] is an enumeration of all the specific error
6/// variants that can occur while processing game replays in the subtr-actor
7/// domain. These include errors related to network frames, frame indexing,
8/// player sets, actor states, object ids, team identities, and data types
9/// amongst others.
10#[derive(Error, Debug, Clone)]
11pub enum SubtrActorErrorVariant {
12    #[error("Replay has no network frames")]
13    NoNetworkFrames,
14
15    #[error("Frame index out of bounds")]
16    FrameIndexOutOfBounds,
17
18    #[error(
19        "Players found in frames that were not part of original set. Found: {found:?}, Original: {original:?}"
20    )]
21    InconsistentPlayerSet {
22        found: std::collections::HashSet<PlayerId>,
23        original: std::collections::HashSet<PlayerId>,
24    },
25
26    #[error(
27        "No update for ActorId {actor_id:?} of ObjectId {object_id:?} after frame {frame_index}"
28    )]
29    NoUpdateAfterFrame {
30        actor_id: boxcars::ActorId,
31        object_id: boxcars::ObjectId,
32        frame_index: usize,
33    },
34
35    #[error("No boost amount value.")]
36    NoBoostAmountValue,
37
38    #[error(
39        "The attribute value that was found was not of the expected type {expected_type} {actual_type:?}"
40    )]
41    UnexpectedAttributeType {
42        expected_type: &'static str,
43        actual_type: &'static str,
44    },
45
46    #[error("ActorId {actor_id:?} has no matching player id")]
47    NoMatchingPlayerId { actor_id: boxcars::ActorId },
48
49    #[error("No game actor")]
50    NoGameActor,
51
52    #[error("ActorId {actor_id:} already exists with object_id {object_id:}")]
53    ActorIdAlreadyExists {
54        actor_id: boxcars::ActorId,
55        object_id: boxcars::ObjectId,
56    },
57
58    #[error("{name:?} actor for player {player_id:?} not found")]
59    ActorNotFound {
60        name: &'static str,
61        player_id: PlayerId,
62    },
63
64    #[error("There was no actor state for actor_id: {actor_id:?}")]
65    NoStateForActorId { actor_id: boxcars::ActorId },
66
67    #[error("Couldn't find object id for {name}")]
68    ObjectIdNotFound { name: &'static str },
69
70    #[error("No value found for derived key {name:?}")]
71    DerivedKeyValueNotFound { name: String },
72
73    #[error("Ball actor not found")]
74    BallActorNotFound,
75
76    #[error("Player team unknown, {player_id:?}")]
77    UnknownPlayerTeam { player_id: PlayerId },
78
79    #[error("Team object id not known {object_id:?}, for player {player_id:?}")]
80    UnknownTeamObjectId {
81        object_id: boxcars::ObjectId,
82        player_id: PlayerId,
83    },
84
85    #[error("Team name was empty for {player_id:?}")]
86    EmptyTeamName { player_id: PlayerId },
87
88    #[error("Error returned to deliberately end processing early")]
89    FinishProcessingEarly,
90
91    #[error("Player stats header not found")]
92    PlayerStatsHeaderNotFound,
93
94    #[error("Interpolation time order was incorrect start_time {start_time:} {time:} {end_time:}")]
95    InterpolationTimeOrderError {
96        start_time: f32,
97        time: f32,
98        end_time: f32,
99    },
100
101    #[error("The updated actor id does not exist {update:?}")]
102    UpdatedActorIdDoesNotExist { update: boxcars::UpdatedAttribute },
103
104    #[error("Could not find {property:} in state")]
105    PropertyNotFoundInState { property: &'static str },
106
107    #[error("Could not build replay meta")]
108    CouldNotBuildReplayMeta,
109
110    #[error("Error converting float")]
111    FloatConversionError,
112
113    #[error(transparent)]
114    NDArrayShapeError(#[from] ::ndarray::ShapeError),
115
116    #[error("{0:?} was not a recognized feature adder")]
117    UnknownFeatureAdderName(String),
118
119    #[error("Callback error: {0}")]
120    CallbackError(String),
121
122    #[error("Unknown builtin stats module '{0}'")]
123    UnknownStatsModuleName(String),
124
125    #[error("Stats serialization error: {0}")]
126    StatsSerializationError(String),
127}
128
129/// [`SubtrActorError`] struct provides an error variant
130/// [`SubtrActorErrorVariant`] along with its backtrace.
131#[derive(Debug)]
132pub struct SubtrActorError {
133    pub backtrace: Backtrace,
134    pub variant: SubtrActorErrorVariant,
135}
136
137impl SubtrActorError {
138    pub fn new(variant: SubtrActorErrorVariant) -> Self {
139        Self {
140            backtrace: if std::env::var_os("SUBTR_ACTOR_ERROR_BACKTRACE").is_some() {
141                Backtrace::capture()
142            } else {
143                Backtrace::disabled()
144            },
145            variant,
146        }
147    }
148
149    pub fn new_result<T>(variant: SubtrActorErrorVariant) -> Result<T, Self> {
150        Err(Self::new(variant))
151    }
152}
153
154#[allow(clippy::result_large_err)]
155pub type SubtrActorResult<T> = Result<T, SubtrActorError>;