Merge pull request #863 from b-guild/errors

impl Display and impl Error for various errors
This commit is contained in:
Dmitry Stepanov
2025-10-24 13:46:02 +03:00
committed by GitHub
15 changed files with 215 additions and 33 deletions
+13
View File
@@ -32,6 +32,7 @@ use ron::ser::PrettyConfig;
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
fmt::Display,
fs::File,
io::Write,
ops::{Deref, DerefMut},
@@ -151,6 +152,18 @@ pub enum SettingsError {
Ron(ron::Error),
}
impl std::error::Error for SettingsError {}
impl Display for SettingsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SettingsError::Io(error) => Display::fmt(error, f),
SettingsError::RonSpanned(error) => Display::fmt(error, f),
SettingsError::Ron(error) => Display::fmt(error, f),
}
}
}
impl From<std::io::Error> for SettingsError {
fn from(e: std::io::Error) -> Self {
Self::Io(e)
+2 -5
View File
@@ -315,13 +315,10 @@ impl Log {
/// be in the log.
pub fn verify<T, E>(result: Result<T, E>)
where
E: Debug,
E: Display,
{
if let Err(e) = result {
Self::writeln(
MessageKind::Error,
format!("Operation failed! Reason: {e:?}"),
);
Self::writeln(MessageKind::Error, format!("Operation failed! Reason: {e}"));
}
}
+2
View File
@@ -143,6 +143,8 @@ pub enum MultiBorrowError<T> {
InvalidHandleGeneration(Handle<T>),
}
impl<T> std::error::Error for MultiBorrowError<T> {}
impl<T> Debug for MultiBorrowError<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(self, f)
+57
View File
@@ -90,6 +90,21 @@ pub enum CastError {
},
}
impl std::error::Error for CastError {}
impl Display for CastError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
CastError::TypeMismatch { property_name, .. } => {
write!(
f,
"Given type does not match expected for property {property_name:?}"
)
}
}
}
}
#[derive(Debug)]
pub struct FieldMetadata<'s> {
/// A name of the property.
@@ -529,6 +544,8 @@ pub enum ReflectPathError<'a> {
NotAnArray,
}
impl std::error::Error for ReflectPathError<'_> {}
impl Display for ReflectPathError<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
@@ -870,6 +887,7 @@ impl ResolvePath for dyn Reflect {
}
}
#[derive(Debug)]
pub enum SetFieldError {
NoSuchField {
name: String,
@@ -881,6 +899,26 @@ pub enum SetFieldError {
},
}
impl std::error::Error for SetFieldError {}
impl Display for SetFieldError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SetFieldError::NoSuchField { name, value } => {
write!(f, "No such field as {name:?} for value {value:?}")
}
SetFieldError::InvalidValue {
field_type_name,
value,
} => write!(
f,
"Invalid value for field type {field_type_name}: {value:?}"
),
}
}
}
#[derive(Debug)]
pub enum SetFieldByPathError<'p> {
InvalidPath {
value: Box<dyn Reflect>,
@@ -893,6 +931,25 @@ pub enum SetFieldByPathError<'p> {
SetFieldError(SetFieldError),
}
impl std::error::Error for SetFieldByPathError<'_> {}
impl Display for SetFieldByPathError<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SetFieldByPathError::InvalidPath { value, reason } => {
write!(f, "Invalid path: {value:?}. Reason: {reason}")
}
SetFieldByPathError::InvalidValue {
field_type_name,
value,
} => {
write!(f, "Invalid value: {value:?}. Type: {field_type_name}")
}
SetFieldByPathError::SetFieldError(set_field_error) => Display::fmt(set_field_error, f),
}
}
}
/// Type-erased API
impl dyn Reflect {
pub fn downcast<T: Reflect>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
+19 -1
View File
@@ -30,7 +30,7 @@ use bitflags::bitflags;
use std::{
any::{Any, TypeId},
cell::Cell,
fmt::Debug,
fmt::{Debug, Display},
ops::{Deref, DerefMut},
};
@@ -83,6 +83,24 @@ pub enum InheritError {
},
}
impl std::error::Error for InheritError {}
impl Display for InheritError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
InheritError::TypesMismatch {
left_type,
right_type,
} => {
write!(
f,
"Child type ({left_type}) does not match parent type ({right_type})"
)
}
}
}
}
/// A wrapper for a variable that hold additional flag that tells that initial value was changed in runtime.
///
/// InheritableVariables are used for resource inheritance system. Resource inheritance may just sound weird,
+8 -2
View File
@@ -701,6 +701,10 @@ impl GlGraphicsServer {
// that also handles HiDPI monitors. It has one issue - if user changes DPI, it won't be handled
// correctly.
if let Some(inner_size) = inner_size {
fn value_to_err(value: fyrox_core::wasm_bindgen::JsValue) -> String {
format!("{:?}", value)
}
let physical_inner_size: PhysicalSize<u32> = inner_size.to_physical(scale_factor);
canvas.set_width(physical_inner_size.width);
@@ -710,12 +714,14 @@ impl GlGraphicsServer {
Log::verify(
canvas
.style()
.set_property("width", &format!("{}px", logical_inner_size.width)),
.set_property("width", &format!("{}px", logical_inner_size.width))
.map_err(value_to_err),
);
Log::verify(
canvas
.style()
.set_property("height", &format!("{}px", logical_inner_size.height)),
.set_property("height", &format!("{}px", logical_inner_size.height))
.map_err(value_to_err),
);
}
+2
View File
@@ -85,6 +85,8 @@ pub enum FrameworkError {
GraphicsServerUnavailable,
}
impl std::error::Error for FrameworkError {}
impl Display for FrameworkError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
+2
View File
@@ -35,6 +35,8 @@ pub enum EngineError {
Custom(String),
}
impl std::error::Error for EngineError {}
impl Display for EngineError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
+2
View File
@@ -69,6 +69,8 @@ pub enum FbxError {
FileLoadError(FileError),
}
impl std::error::Error for FbxError {}
impl Display for FbxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
+35
View File
@@ -20,6 +20,8 @@
//! Skybox is a huge box around a camera. See [`SkyBox`] docs for more info.
use std::fmt::Display;
use crate::{
asset::{builtin::BuiltInResource, embedded_data_source, untyped::ResourceKind},
core::{log::Log, reflect::prelude::*, uuid_provider, visitor::prelude::*},
@@ -377,6 +379,39 @@ pub enum SkyBoxError {
},
}
impl std::error::Error for SkyBoxError {}
impl Display for SkyBoxError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SkyBoxError::UnsupportedTextureKind(texture_kind) => {
write!(f, "Unsupported texture kind: {texture_kind:?}")
}
SkyBoxError::UnableToBuildCubeMap => f.write_str("Cube map was failed to build."),
SkyBoxError::NonSquareTexture {
index,
width,
height,
} => write!(
f,
"Input texture is not square. Index: {index}, width: {width}, height: {height}"
),
SkyBoxError::DifferentTexture {
expected_width,
expected_height,
expected_pixel_kind,
index,
actual_width,
actual_height,
actual_pixel_kind,
} => write!(f, "Some input texture differs in size or pixel kind. Index: {index}. \
Expected width: {expected_width}, height: {expected_height}, kind: {expected_pixel_kind:?}. \
Actual width: {actual_width}, height: {actual_height}, kind: {actual_pixel_kind:?}."),
SkyBoxError::TextureIsNotReady { index } => write!(f, "Input texture is not loaded. Index: {index}"),
}
}
}
/// SkyBox builder is used to create new skybox in declarative manner.
pub struct SkyBoxBuilder {
/// Texture for front face.
+2
View File
@@ -309,6 +309,8 @@ pub enum LightmapGenerationError {
InvalidData(VertexFetchError),
}
impl std::error::Error for LightmapGenerationError {}
impl Display for LightmapGenerationError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
+14 -14
View File
@@ -47,13 +47,17 @@ pub trait ImportOptions:
{
/// Saves import options into a specified file.
fn save_internal(&self, path: &Path) -> bool {
if let Ok(mut file) = File::create(path) {
if let Ok(string) = ron::ser::to_string_pretty(self, PrettyConfig::default()) {
Log::verify(file.write_all(string.as_bytes()));
return true;
}
fn write<T: Serialize>(this: &T, path: &Path) -> std::io::Result<()> {
let mut file = File::create(path)?;
let string = ron::ser::to_string_pretty(this, PrettyConfig::default())
.map_err(|e| std::io::Error::new(ErrorKind::InvalidData, e))?;
file.write_all(string.as_bytes())?;
Ok(())
}
false
let result = write(self, path);
let is_ok = result.is_ok();
Log::verify(result);
is_ok
}
}
@@ -79,10 +83,8 @@ where
Ok(options) => Some(options),
Err(e) => {
Log::warn(format!(
"Malformed options file {} for {} resource, fallback to defaults! Reason: {:?}",
settings_path.display(),
resource_path.display(),
e
"Malformed options file {:?}, fallback to defaults! Reason: {}",
settings_path, e
));
None
@@ -99,10 +101,8 @@ where
}
Log::warn(format!(
"Unable to load options file {} for {} resource, fallback to defaults! Reason: {:?}",
settings_path.display(),
resource_path.display(),
e
"Unable to load options file {:?}, fallback to defaults! Reason: {}",
settings_path, e
));
None
+49 -9
View File
@@ -58,7 +58,7 @@ use fyrox_graph::{
};
use std::{
any::{Any, TypeId},
fmt::{Debug, Formatter},
fmt::{Debug, Display, Formatter},
ops::{Deref, DerefMut},
sync::Arc,
};
@@ -131,6 +131,26 @@ pub enum PropertyAction {
Revert,
}
impl Display for PropertyAction {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
PropertyAction::Modify { value } => write!(
f,
"A property needs to be modified with given value: {value:?}"
),
PropertyAction::AddItem { value } => write!(
f,
"An item needs to be added to a collection property: {value:?}"
),
PropertyAction::RemoveItem { index } => write!(
f,
"An item needs to be removed from a collection property. Index: {index}"
),
PropertyAction::Revert => f.write_str("Revert value to parent"),
}
}
}
impl PropertyAction {
/// Creates action from a field definition. It is recursive action, it traverses the tree
/// until there is either FieldKind::Object or FieldKind::Collection. FieldKind::Inspectable
@@ -647,14 +667,13 @@ impl Inspector {
if let Some(inspector) = ui.try_get_of_type::<Inspector>(inspector) {
let ctx = inspector.context.clone();
Log::verify(ctx.sync(
object,
ui,
0,
true,
Default::default(),
Default::default(),
));
if let Err(errs) =
ctx.sync(object, ui, 0, true, Default::default(), Default::default())
{
for err in errs {
Log::err(err.to_string());
}
}
}
}
}
@@ -710,6 +729,27 @@ pub enum InspectorError {
Group(Vec<InspectorError>),
}
impl std::error::Error for InspectorError {}
impl Display for InspectorError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
InspectorError::CastError(cast_error) => Display::fmt(cast_error, f),
InspectorError::OutOfSync => f.write_str(
"The object type has changed and the inspector context is no longer valid.",
),
InspectorError::Custom(message) => f.write_str(message),
InspectorError::Group(inspector_errors) => {
f.write_str("Multiple errors:\n")?;
for err in inspector_errors {
writeln!(f, " {err}")?;
}
Ok(())
}
}
}
}
impl From<CastError> for InspectorError {
fn from(e: CastError) -> Self {
Self::CastError(e)
+6 -2
View File
@@ -302,14 +302,18 @@ impl SettingsWindow {
.context()
.clone();
Log::verify(ctx.sync(
if let Err(errs) = ctx.sync(
&**settings,
ui,
0,
true,
Default::default(),
Default::default(),
));
) {
for err in errs {
Log::err(err.to_string());
}
}
}
}
+2
View File
@@ -67,6 +67,8 @@ pub enum NameError {
InvalidCharacter(char),
}
impl std::error::Error for NameError {}
impl Display for NameError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {