1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
// -------------------------------------------------------------------------
// Error Handling and Field Type
// -------------------------------------------------------------------------
use crate::{deserialize2::EventType, CowStr, IntoStatic, Value};
/// A content-less variant of the [`Value`] enum, used for reporting errors, see [`MerdeError::MismatchedType`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ValueType {
/// The value is `null`.
Null,
/// The value is `true` or `false`.
Bool,
/// The value fits in an `i64`.
Int,
/// The value no longer fits in an `i64`.
BigInt,
/// The value has decimal places.
Float,
/// The value is a string.
String,
/// The value is a byte array.
Bytes,
/// The value is an array.
Array,
/// The value is a map (associating keys and values)
Map,
}
/// A grab-bag of errors that can occur when deserializing.
/// This isn't super clean, not my proudest moment.
#[derive(Debug)]
#[non_exhaustive]
pub enum MerdeError<'s> {
/// We expected a certain type but got a different one.
MismatchedType {
/// The expected type.
expected: ValueType,
/// The type we got.
found: ValueType,
},
/// We expected an object to have a certain property, but it was missing.
MissingProperty(CowStr<'s>),
/// We tried to access an array index that was out of bounds.
IndexOutOfBounds {
/// The index we tried to access.
index: usize,
/// The length of the array.
len: usize,
},
/// We encountered a property that we didn't expect.
UnknownProperty(CowStr<'s>),
/// For example, we had a `u8` field but the JSON value was bigger than `u8::MAX`.
OutOfRange,
/// A field was missing (but we don't know its name)
MissingValue,
/// While calling out to [`FromStr::from_str`](std::str::FromStr::from_str) to build a [`HashMap`](std::collections::HashMap), we got an error.
InvalidKey {
key: CowStr<'s>,
type_name: &'static str,
},
/// While parsing a datetime, we got an error
InvalidDateTimeValue,
UnexpectedEvent {
got: EventType,
expected: &'static [EventType],
},
/// An I/O error occurred.
Io(std::io::Error),
}
impl IntoStatic for MerdeError<'_> {
type Output = MerdeError<'static>;
fn into_static(self) -> MerdeError<'static> {
match self {
MerdeError::MismatchedType { expected, found } => {
MerdeError::MismatchedType { expected, found }
}
MerdeError::MissingProperty(prop) => MerdeError::MissingProperty(prop.into_static()),
MerdeError::IndexOutOfBounds { index, len } => {
MerdeError::IndexOutOfBounds { index, len }
}
MerdeError::UnknownProperty(prop) => MerdeError::UnknownProperty(prop.into_static()),
MerdeError::OutOfRange => MerdeError::OutOfRange,
MerdeError::MissingValue => MerdeError::MissingValue,
MerdeError::InvalidKey { key, type_name } => MerdeError::InvalidKey {
key: key.into_static(),
type_name,
},
MerdeError::InvalidDateTimeValue => MerdeError::InvalidDateTimeValue,
MerdeError::Io(e) => MerdeError::Io(e),
MerdeError::UnexpectedEvent { got, expected } => {
MerdeError::UnexpectedEvent { got, expected }
}
}
}
}
impl From<std::io::Error> for MerdeError<'_> {
fn from(e: std::io::Error) -> Self {
MerdeError::Io(e)
}
}
impl std::fmt::Display for MerdeError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MerdeError::MismatchedType { expected, found } => {
write!(f, "Expected {:?}, found {:?}", expected, found)
}
MerdeError::MissingProperty(prop) => {
write!(f, "Missing property: {}", prop)
}
MerdeError::IndexOutOfBounds { index, len: length } => {
write!(
f,
"Index out of bounds: index {} is not valid for length {}",
index, length
)
}
MerdeError::UnknownProperty(prop) => {
write!(f, "Unknown property: {}", prop)
}
MerdeError::OutOfRange => {
write!(f, "Value is out of range")
}
MerdeError::MissingValue => {
write!(f, "Missing value")
}
MerdeError::InvalidKey { key, type_name } => {
write!(
f,
"Invalid key: couldn't convert {:?} to type {}",
key, type_name
)
}
MerdeError::InvalidDateTimeValue => {
write!(f, "Invalid date/time value")
}
MerdeError::Io(e) => {
write!(f, "I/O error: {}", e)
}
MerdeError::UnexpectedEvent { got, expected } => {
write!(
f,
"Unexpected event: got {:?}, expected one of {:?}",
got, expected
)
}
}
}
}
impl<'s> std::error::Error for MerdeError<'s> {}
impl Value<'_> {
/// Returns the [ValueType] for a given [Value].
pub fn value_type(&self) -> ValueType {
match self {
Value::Null => ValueType::Null,
Value::Bool(_) => ValueType::Bool,
Value::Int(_) => ValueType::Int,
Value::Float(_) => ValueType::Float,
Value::Str(_) => ValueType::String,
Value::Bytes(_) => ValueType::Bytes,
Value::Array(_) => ValueType::Array,
Value::Map(_) => ValueType::Map,
}
}
}