fyrox_impl/plugin/
error.rs1use crate::{
24 asset::state::LoadError,
25 core::{dyntype::DynTypeError, pool::PoolError, visitor::error::VisitError, warn},
26 graphics::error::FrameworkError,
27 scene::graph::GraphError,
28};
29use std::{
30 backtrace::Backtrace,
31 fmt::{Debug, Display, Formatter},
32 sync::atomic::{AtomicBool, Ordering},
33};
34
35static CAPTURE_BACKTRACE: AtomicBool = AtomicBool::new(false);
36
37pub fn enable_backtrace_capture(capture: bool) {
40 CAPTURE_BACKTRACE.store(capture, Ordering::Relaxed);
41
42 if capture {
43 warn!(
44 "Backtrace capture is enabled! This will negatively impact performance in \
45 case of error spam."
46 )
47 }
48}
49
50pub fn is_capturing_backtrace() -> bool {
52 CAPTURE_BACKTRACE.load(Ordering::Relaxed)
53}
54
55pub enum GameErrorKind {
57 GraphError(GraphError),
59 PoolError(PoolError),
61 UserError(UserError),
63 VisitError(VisitError),
65 ResourceLoadError(LoadError),
67 DynTypeError(DynTypeError),
69 StringError(String),
71 FrameworkError(FrameworkError),
73}
74
75pub struct GameError {
77 pub kind: GameErrorKind,
79 pub trace: Option<Backtrace>,
81}
82
83impl GameError {
84 pub fn new(kind: GameErrorKind) -> Self {
86 Self {
87 kind,
88 trace: if is_capturing_backtrace() {
89 Some(Backtrace::force_capture())
90 } else {
91 None
92 },
93 }
94 }
95
96 pub fn user(value: impl std::error::Error + Send + 'static) -> Self {
98 Self::new(GameErrorKind::UserError(Box::new(value)))
99 }
100
101 pub fn str(value: impl AsRef<str>) -> Self {
103 Self::new(GameErrorKind::StringError(value.as_ref().to_string()))
104 }
105}
106
107impl From<GraphError> for GameError {
108 fn from(value: GraphError) -> Self {
109 Self::new(GameErrorKind::GraphError(value))
110 }
111}
112
113impl From<PoolError> for GameError {
114 fn from(value: PoolError) -> Self {
115 Self::new(GameErrorKind::PoolError(value))
116 }
117}
118
119impl From<UserError> for GameError {
120 fn from(value: UserError) -> Self {
121 Self::new(GameErrorKind::UserError(value))
122 }
123}
124
125impl From<LoadError> for GameError {
126 fn from(value: LoadError) -> Self {
127 Self::new(GameErrorKind::ResourceLoadError(value))
128 }
129}
130
131impl From<VisitError> for GameError {
132 fn from(value: VisitError) -> Self {
133 Self::new(GameErrorKind::VisitError(value))
134 }
135}
136
137impl From<DynTypeError> for GameError {
138 fn from(value: DynTypeError) -> Self {
139 Self::new(GameErrorKind::DynTypeError(value))
140 }
141}
142
143impl From<FrameworkError> for GameError {
144 fn from(value: FrameworkError) -> Self {
145 Self::new(GameErrorKind::FrameworkError(value))
146 }
147}
148
149impl std::error::Error for GameError {}
150
151impl Display for GameError {
152 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
153 match self.trace.as_ref() {
154 Some(trace) => {
155 write!(f, "{}\nBacktrace:\n{}", self.kind, trace)
156 }
157 None => {
158 write!(
159 f,
160 "{}\nBacktrace is unavailable, call `enable_backtrace_capture(true)` to \
161 enable backtrace capture. Keep in mind that it may be very slow!",
162 self.kind
163 )
164 }
165 }
166 }
167}
168
169impl Display for GameErrorKind {
170 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
171 match self {
172 Self::GraphError(err) => Display::fmt(&err, f),
173 Self::PoolError(err) => Display::fmt(&err, f),
174 Self::UserError(err) => Display::fmt(&err, f),
175 Self::ResourceLoadError(err) => Display::fmt(&err, f),
176 Self::VisitError(err) => Display::fmt(&err, f),
177 Self::DynTypeError(err) => Display::fmt(&err, f),
178 Self::StringError(msg) => {
179 write!(f, "{msg}")
180 }
181 Self::FrameworkError(err) => Display::fmt(&err, f),
182 }
183 }
184}
185
186impl Debug for GameError {
187 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
188 write!(f, "{}", self)
189 }
190}
191
192pub type GameResult = Result<(), GameError>;
194
195pub type UserError = Box<dyn std::error::Error + Send>;