Skip to main content

fyrox_core/visitor/
error.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Possible errors that may occur during serialization/deserialization.
22
23use crate::io::FileError;
24use crate::visitor::Visitor;
25use base64::DecodeError;
26use std::num::{ParseFloatError, ParseIntError};
27use std::{
28    error::Error,
29    fmt::{Display, Formatter},
30    string::FromUtf8Error,
31};
32
33/// Errors that may occur while reading or writing [`crate::visitor::Visitor`].
34#[derive(Debug)]
35pub enum VisitError {
36    /// An error that occured for multiple reasons, when there are multiple potential ways
37    /// to visit a node, and all of them lead to errors.
38    Multiple(Vec<VisitError>),
39    /// An [std::io::Error] occured while reading or writing a file with Visitor data.
40    Io(std::io::Error),
41    /// When a field is encoded as bytes, the field data is prefixed by an identifying byte
42    /// to allow the bytes to be decoded. This error happens when an identifying byte is
43    /// expected during decoding, but an unknown value is found in that byte.
44    UnknownFieldType(u8),
45    /// Attempting to visit a field on a read-mode Visitor when no field in the visitor data
46    /// has the given name.
47    FieldDoesNotExist(String),
48    /// Attempting to visit a field on a write-mode Visitor when a field already has the
49    /// given name.
50    FieldAlreadyExists(String),
51    /// Attempting to enter a region on a write-mode Visitor when a region already has the
52    /// given name.
53    RegionAlreadyExists(String),
54    /// Current node handle is invalid and does not lead to a real node.
55    InvalidCurrentNode,
56    /// Attempting to visit a field using a read-mode Visitor when that field was originally
57    /// written using a value of a different type.
58    FieldTypeDoesNotMatch {
59        /// expected [`crate::visitor::FieldKind`] variant name, for instance "FieldKind::F64"
60        expected: &'static str,
61        /// Debug representation of actual [`crate::visitor::FieldKind`]
62        actual: String,
63    },
64    /// Attempting to enter a region on a read-mode Visitor when no region in the visitor's data
65    /// has the given name.
66    RegionDoesNotExist(String),
67    /// The Visitor tried to leave is current node, but somehow it had no current node. This should never happen.
68    NoActiveNode,
69    /// The [`crate::Visitor::MAGIC_BINARY_CURRENT`], [`crate::Visitor::MAGIC_ASCII_CURRENT`].
70    /// bytes were missing from the beginning of encoded Visitor data.
71    NotSupportedFormat,
72    /// Some sequence of bytes was not in UTF8 format.
73    InvalidName,
74    /// Visitor data can be self-referential, such as when the data contains multiple `Rc` references
75    /// to a single shared value. This causes the visitor to store the data once and then later references
76    /// to the same value point back to its first occurrence. This error occurs if one of these references
77    /// points to a value of the wrong type.
78    TypeMismatch {
79        /// The type that was visiting when the error occurred.
80        expected: &'static str,
81        /// The type that was stored in the `Rc` or `Arc`.
82        actual: &'static str,
83    },
84    /// Attempting to visit a mutably borrowed RefCell.
85    RefCellAlreadyMutableBorrowed,
86    /// A plain-text error message that could indicate almost anything.
87    User(String),
88    /// `Rc` and `Arc` values store an "Id" value in the Visitor data which is based in their internal pointer.
89    /// This error indicates that while reading this data, one of those Id values was discovered by be 0.
90    UnexpectedRcNullIndex,
91    /// A poison error occurred while trying to visit a mutex.
92    PoisonedMutex,
93    /// A FileLoadError was encountered while trying to decode Visitor data from a file.
94    FileLoadError(FileError),
95    /// Integer parsing error.
96    ParseIntError(ParseIntError),
97    /// Floating point number parsing error.
98    ParseFloatError(ParseFloatError),
99    /// An error occurred when trying to decode base64-encoded data.
100    DecodeError(DecodeError),
101    /// An error occurred when trying to parse uuid from a string.
102    UuidError(uuid::Error),
103    /// Arbitrary error.
104    Any(Box<dyn Error + Send + Sync>),
105}
106
107impl Error for VisitError {}
108
109impl VisitError {
110    /// Create a [`VisitError::FieldDoesNotExist`] containing the given field name and the
111    /// breadcrumbs of the current visitor node.
112    pub fn field_does_not_exist(name: &str, visitor: &Visitor) -> Self {
113        Self::FieldDoesNotExist(visitor.breadcrumbs() + " > " + name)
114    }
115    /// Create an error from two errors.
116    pub fn multiple(self, other: Self) -> Self {
117        match (self, other) {
118            (Self::Multiple(mut a), Self::Multiple(mut b)) => {
119                a.append(&mut b);
120                Self::Multiple(a)
121            }
122            (Self::Multiple(mut a), b) => {
123                a.push(b);
124                Self::Multiple(a)
125            }
126            (a, Self::Multiple(mut b)) => {
127                b.push(a);
128                Self::Multiple(b)
129            }
130            (a, b) => Self::Multiple(vec![a, b]),
131        }
132    }
133}
134
135impl Display for VisitError {
136    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
137        match self {
138            Self::Multiple(errs) => {
139                write!(f, "multiple errors:[")?;
140                for err in errs {
141                    write!(f, "{err};")?;
142                }
143                write!(f, "]")
144            }
145            Self::Io(io) => write!(f, "io error: {io}"),
146            Self::UnknownFieldType(type_index) => write!(f, "unknown field type {type_index}"),
147            Self::FieldDoesNotExist(name) => write!(f, "field does not exist: {name}"),
148            Self::FieldAlreadyExists(name) => write!(f, "field already exists {name}"),
149            Self::RegionAlreadyExists(name) => write!(f, "region already exists {name}"),
150            Self::InvalidCurrentNode => write!(f, "invalid current node"),
151            Self::FieldTypeDoesNotMatch { expected, actual } => write!(
152                f,
153                "field type does not match. expected: {expected}, actual: {actual}"
154            ),
155            Self::RegionDoesNotExist(name) => write!(f, "region does not exist: {name}"),
156            Self::NoActiveNode => write!(f, "no active node"),
157            Self::NotSupportedFormat => write!(f, "not supported format"),
158            Self::InvalidName => write!(f, "invalid name"),
159            Self::TypeMismatch { expected, actual } => {
160                write!(f, "type mismatch. expected: {expected}, actual: {actual}")
161            }
162            Self::RefCellAlreadyMutableBorrowed => write!(f, "ref cell already mutable borrowed"),
163            Self::User(msg) => write!(f, "user defined error: {msg}"),
164            Self::UnexpectedRcNullIndex => write!(f, "unexpected rc null index"),
165            Self::PoisonedMutex => write!(f, "attempt to lock poisoned mutex"),
166            Self::FileLoadError(e) => write!(f, "file load error: {e:?}"),
167            Self::ParseIntError(e) => write!(f, "unable to parse integer: {e:?}"),
168            Self::ParseFloatError(e) => write!(f, "unable to parse float: {e:?}"),
169            Self::DecodeError(e) => write!(f, "base64 decoding error: {e:?}"),
170            Self::UuidError(e) => write!(f, "uuid error: {e:?}"),
171            Self::Any(e) => {
172                write!(f, "{e}")
173            }
174        }
175    }
176}
177
178impl<T> From<std::sync::PoisonError<std::sync::MutexGuard<'_, T>>> for VisitError {
179    fn from(_: std::sync::PoisonError<std::sync::MutexGuard<'_, T>>) -> Self {
180        Self::PoisonedMutex
181    }
182}
183
184impl<T> From<std::sync::PoisonError<&mut T>> for VisitError {
185    fn from(_: std::sync::PoisonError<&mut T>) -> Self {
186        Self::PoisonedMutex
187    }
188}
189
190impl<T> From<std::sync::PoisonError<std::sync::RwLockWriteGuard<'_, T>>> for VisitError {
191    fn from(_: std::sync::PoisonError<std::sync::RwLockWriteGuard<'_, T>>) -> Self {
192        Self::PoisonedMutex
193    }
194}
195
196impl From<std::io::Error> for VisitError {
197    fn from(io_err: std::io::Error) -> Self {
198        Self::Io(io_err)
199    }
200}
201
202impl From<FromUtf8Error> for VisitError {
203    fn from(_: FromUtf8Error) -> Self {
204        Self::InvalidName
205    }
206}
207
208impl From<String> for VisitError {
209    fn from(s: String) -> Self {
210        Self::User(s)
211    }
212}
213
214impl From<FileError> for VisitError {
215    fn from(e: FileError) -> Self {
216        Self::FileLoadError(e)
217    }
218}
219
220impl From<ParseIntError> for VisitError {
221    fn from(value: ParseIntError) -> Self {
222        Self::ParseIntError(value)
223    }
224}
225
226impl From<ParseFloatError> for VisitError {
227    fn from(value: ParseFloatError) -> Self {
228        Self::ParseFloatError(value)
229    }
230}
231
232impl From<DecodeError> for VisitError {
233    fn from(value: DecodeError) -> Self {
234        Self::DecodeError(value)
235    }
236}
237
238impl From<uuid::Error> for VisitError {
239    fn from(value: uuid::Error) -> Self {
240        Self::UuidError(value)
241    }
242}
243
244impl From<Box<dyn Error + Send + Sync>> for VisitError {
245    fn from(value: Box<dyn Error + Send + Sync>) -> Self {
246        Self::Any(value)
247    }
248}