mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-26 21:46:33 +11:00
Improve error type
This commit is contained in:
parent
2a266fb091
commit
158eba1d15
13 changed files with 207 additions and 135 deletions
|
@ -4,7 +4,6 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
byteorder = "1.4.3"
|
||||
cesu8 = "1.1.0"
|
||||
indexmap = { version = "1.9.1", features = ["serde"] }
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::Read;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use serde::de::value::StrDeserializer;
|
||||
use serde::de::{DeserializeSeed, Error as _, SeqAccess, Unexpected, Visitor};
|
||||
|
@ -111,7 +110,7 @@ impl<'de: 'r, 'r, R: Read + ?Sized> Deserializer<'de> for ArrayDeserializer<'r,
|
|||
let len = self.reader.read_i32::<BigEndian>()?;
|
||||
|
||||
if len < 0 {
|
||||
return Err(Error(anyhow!("array with negative length")));
|
||||
return Err(Error::new_static("array with negative length"));
|
||||
}
|
||||
|
||||
visitor.visit_seq(ArraySeqAccess {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::Read;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::ReadBytesExt;
|
||||
use serde::de;
|
||||
use serde::de::DeserializeSeed;
|
||||
|
@ -44,7 +43,7 @@ impl<'de: 'r, 'r, R: Read + ?Sized> de::MapAccess<'de> for MapAccess<'r, R> {
|
|||
})
|
||||
.map(Some)
|
||||
.map_err(|e| match self.fields {
|
||||
[f, ..] => e.context(anyhow!("compound key (field `{f}`)")),
|
||||
[f, ..] => e.field(*f),
|
||||
[] => e,
|
||||
})
|
||||
}
|
||||
|
@ -54,7 +53,7 @@ impl<'de: 'r, 'r, R: Read + ?Sized> de::MapAccess<'de> for MapAccess<'r, R> {
|
|||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
if self.value_tag == Tag::End {
|
||||
return Err(Error(anyhow!("end of compound?")));
|
||||
return Err(Error::new_static("end of compound?"));
|
||||
}
|
||||
|
||||
let field = match self.fields {
|
||||
|
@ -70,7 +69,7 @@ impl<'de: 'r, 'r, R: Read + ?Sized> de::MapAccess<'de> for MapAccess<'r, R> {
|
|||
tag: self.value_tag,
|
||||
})
|
||||
.map_err(|e| match field {
|
||||
Some(f) => e.context(anyhow!("compound value (field `{f}`)")),
|
||||
Some(f) => e.field(f),
|
||||
None => e,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
use std::io::Read;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use cesu8::from_java_cesu8;
|
||||
use serde::de::Visitor;
|
||||
|
@ -11,7 +10,7 @@ use smallvec::SmallVec;
|
|||
use crate::binary::de::array::EnumAccess;
|
||||
use crate::binary::de::compound::MapAccess;
|
||||
use crate::binary::de::list::SeqAccess;
|
||||
use crate::{ArrayType, Error, Tag};
|
||||
use crate::{ArrayType, Error, Tag, CESU8_DECODE_ERROR};
|
||||
|
||||
pub(super) struct PayloadDeserializer<'w, R: ?Sized> {
|
||||
pub reader: &'w mut R,
|
||||
|
@ -50,7 +49,7 @@ impl<'de: 'w, 'w, R: Read + ?Sized> de::Deserializer<'de> for PayloadDeserialize
|
|||
buf.push(self.reader.read_u8()?);
|
||||
}
|
||||
|
||||
match from_java_cesu8(&buf).map_err(|e| Error(anyhow!(e)))? {
|
||||
match from_java_cesu8(&buf).map_err(|_| Error::new_static(CESU8_DECODE_ERROR))? {
|
||||
Cow::Borrowed(s) => visitor.visit_str(s),
|
||||
Cow::Owned(string) => visitor.visit_string(string),
|
||||
}
|
||||
|
@ -60,13 +59,13 @@ impl<'de: 'w, 'w, R: Read + ?Sized> de::Deserializer<'de> for PayloadDeserialize
|
|||
let len = self.reader.read_i32::<BigEndian>()?;
|
||||
|
||||
if len < 0 {
|
||||
return Err(Error(anyhow!("list with negative length")));
|
||||
return Err(Error::new_static("list with negative length"));
|
||||
}
|
||||
|
||||
if element_tag == Tag::End && len != 0 {
|
||||
return Err(Error(anyhow!(
|
||||
"list with TAG_End element type must have length zero"
|
||||
)));
|
||||
return Err(Error::new_static(
|
||||
"list with TAG_End element type must have length zero",
|
||||
));
|
||||
}
|
||||
|
||||
visitor.visit_seq(SeqAccess {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
use std::io::Read;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use cesu8::from_java_cesu8;
|
||||
use serde::de::Visitor;
|
||||
|
@ -9,7 +8,7 @@ use serde::{forward_to_deserialize_any, Deserializer};
|
|||
use smallvec::SmallVec;
|
||||
|
||||
use crate::binary::de::payload::PayloadDeserializer;
|
||||
use crate::{Error, Tag};
|
||||
use crate::{Error, Tag, CESU8_DECODE_ERROR};
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct RootDeserializer<R> {
|
||||
|
@ -31,7 +30,7 @@ impl<R: Read> RootDeserializer<R> {
|
|||
let tag = Tag::from_u8(self.reader.read_u8()?)?;
|
||||
|
||||
if tag != Tag::Compound {
|
||||
return Err(Error(anyhow!(
|
||||
return Err(Error::new_owned(format!(
|
||||
"unexpected tag `{tag}` (root value must be a compound)"
|
||||
)));
|
||||
}
|
||||
|
@ -42,7 +41,7 @@ impl<R: Read> RootDeserializer<R> {
|
|||
buf.push(self.reader.read_u8()?);
|
||||
}
|
||||
|
||||
match from_java_cesu8(&buf).map_err(|e| Error(anyhow!(e)))? {
|
||||
match from_java_cesu8(&buf).map_err(|_| Error::new_static(CESU8_DECODE_ERROR))? {
|
||||
Cow::Borrowed(s) => s.clone_into(&mut self.root_name),
|
||||
Cow::Owned(s) => self.root_name = s,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use cesu8::to_java_cesu8;
|
||||
pub use root::RootSerializer as Serializer;
|
||||
|
@ -28,7 +27,7 @@ fn write_string(mut writer: impl Write, string: &str) -> Result<()> {
|
|||
let data = to_java_cesu8(string);
|
||||
match data.len().try_into() {
|
||||
Ok(len) => writer.write_u16::<BigEndian>(len)?,
|
||||
Err(_) => return Err(Error(anyhow!("string byte length exceeds u16::MAX"))),
|
||||
Err(_) => return Err(Error::new_static("string byte length exceeds u16::MAX")),
|
||||
};
|
||||
|
||||
writer.write_all(&data)?;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::WriteBytesExt;
|
||||
use serde::{ser, Serialize, Serializer};
|
||||
|
||||
|
@ -20,16 +19,18 @@ impl<'w, W: Write + ?Sized> ser::SerializeMap for SerializeMap<'w, W> {
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Err(Error(anyhow!("map keys cannot be serialized individually")))
|
||||
Err(Error::new_static(
|
||||
"map keys cannot be serialized individually",
|
||||
))
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, _value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Err(Error(anyhow!(
|
||||
"map values cannot be serialized individually"
|
||||
)))
|
||||
Err(Error::new_static(
|
||||
"map values cannot be serialized individually",
|
||||
))
|
||||
}
|
||||
|
||||
fn serialize_entry<K: ?Sized, V: ?Sized>(
|
||||
|
@ -57,8 +58,14 @@ struct MapEntrySerializer<'w, 'v, W: ?Sized, V: ?Sized> {
|
|||
value: &'v V,
|
||||
}
|
||||
|
||||
fn key_not_a_string<T>(typ: &str) -> Result<T, Error> {
|
||||
Err(Error(anyhow!("map keys must be strings (got {typ})")))
|
||||
macro_rules! non_string_map_key {
|
||||
($typ:literal) => {
|
||||
Err(Error::new_static(concat!(
|
||||
"map keys must be strings (got ",
|
||||
$typ,
|
||||
")"
|
||||
)))
|
||||
};
|
||||
}
|
||||
|
||||
impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer<'_, '_, W, V> {
|
||||
|
@ -73,80 +80,80 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
type SerializeStructVariant = Impossible;
|
||||
|
||||
fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("bool")
|
||||
non_string_map_key!("bool")
|
||||
}
|
||||
|
||||
fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("i8")
|
||||
non_string_map_key!("i8")
|
||||
}
|
||||
|
||||
fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("i16")
|
||||
non_string_map_key!("i16")
|
||||
}
|
||||
|
||||
fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("i32")
|
||||
non_string_map_key!("i32")
|
||||
}
|
||||
|
||||
fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("i64")
|
||||
non_string_map_key!("i64")
|
||||
}
|
||||
|
||||
fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("u8")
|
||||
non_string_map_key!("u8")
|
||||
}
|
||||
|
||||
fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("u16")
|
||||
non_string_map_key!("u16")
|
||||
}
|
||||
|
||||
fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("u32")
|
||||
non_string_map_key!("u32")
|
||||
}
|
||||
|
||||
fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("u64")
|
||||
non_string_map_key!("u64")
|
||||
}
|
||||
|
||||
fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("f32")
|
||||
non_string_map_key!("f32")
|
||||
}
|
||||
|
||||
fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("f64")
|
||||
non_string_map_key!("f64")
|
||||
}
|
||||
|
||||
fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("char")
|
||||
non_string_map_key!("char")
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
||||
self.value
|
||||
.serialize(&mut PayloadSerializer::named(self.writer, v))
|
||||
.map_err(|e| e.context(format!("key `{v}`")))
|
||||
.map_err(|e| e.field(format!("{v}")))
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("&[u8]")
|
||||
non_string_map_key!("&[u8]")
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("None")
|
||||
non_string_map_key!("None")
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
key_not_a_string("Some")
|
||||
non_string_map_key!("Some")
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("()")
|
||||
non_string_map_key!("()")
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("unit struct")
|
||||
non_string_map_key!("unit struct")
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
|
@ -155,7 +162,7 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
key_not_a_string("unit variant")
|
||||
non_string_map_key!("unit variant")
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
|
@ -166,7 +173,7 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
key_not_a_string("newtype struct")
|
||||
non_string_map_key!("newtype struct")
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
|
@ -179,15 +186,15 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
key_not_a_string("newtype variant")
|
||||
non_string_map_key!("newtype variant")
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
key_not_a_string("seq")
|
||||
non_string_map_key!("seq")
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||
key_not_a_string("tuple")
|
||||
non_string_map_key!("tuple")
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
|
@ -195,7 +202,7 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
_name: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
key_not_a_string("tuple struct")
|
||||
non_string_map_key!("tuple struct")
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(
|
||||
|
@ -205,11 +212,11 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
key_not_a_string("tuple variant")
|
||||
non_string_map_key!("tuple variant")
|
||||
}
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
key_not_a_string("map")
|
||||
non_string_map_key!("map")
|
||||
}
|
||||
|
||||
fn serialize_struct(
|
||||
|
@ -217,7 +224,7 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
_name: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
key_not_a_string("struct")
|
||||
non_string_map_key!("struct")
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(
|
||||
|
@ -227,7 +234,7 @@ impl<W: Write + ?Sized, V: Serialize + ?Sized> Serializer for MapEntrySerializer
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
key_not_a_string("struct variant")
|
||||
non_string_map_key!("struct variant")
|
||||
}
|
||||
|
||||
fn is_human_readable(&self) -> bool {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
|
@ -70,9 +69,9 @@ impl<'w, 'n, W: Write + ?Sized> PayloadSerializer<'w, 'n, W> {
|
|||
}
|
||||
State::SeqElement { element_type } => {
|
||||
if tag != *element_type {
|
||||
return Err(Error(anyhow!(
|
||||
return Err(Error::new_owned(format!(
|
||||
"list/array elements must be homogeneous (got {tag}, expected \
|
||||
{element_type})",
|
||||
{element_type})"
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +82,7 @@ impl<'w, 'n, W: Write + ?Sized> PayloadSerializer<'w, 'n, W> {
|
|||
ArrayType::Long => "a long array",
|
||||
};
|
||||
|
||||
return Err(Error(anyhow!(
|
||||
return Err(Error::new_owned(format!(
|
||||
"expected a seq for {msg}, got {tag} instead"
|
||||
)));
|
||||
}
|
||||
|
@ -93,9 +92,10 @@ impl<'w, 'n, W: Write + ?Sized> PayloadSerializer<'w, 'n, W> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unsupported<T>(typ: &str) -> Result<T, Error> {
|
||||
Err(Error(anyhow!("{typ} is not supported")))
|
||||
macro_rules! unsupported {
|
||||
($typ:literal) => {
|
||||
Err(Error::new_static(concat!($typ, " is not supported")))
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W> {
|
||||
|
@ -135,19 +135,19 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
}
|
||||
|
||||
fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("u8")
|
||||
unsupported!("u8")
|
||||
}
|
||||
|
||||
fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("u16")
|
||||
unsupported!("u16")
|
||||
}
|
||||
|
||||
fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("u32")
|
||||
unsupported!("u32")
|
||||
}
|
||||
|
||||
fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("u64")
|
||||
unsupported!("u64")
|
||||
}
|
||||
|
||||
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
|
||||
|
@ -161,7 +161,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
}
|
||||
|
||||
fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("char")
|
||||
unsupported!("char")
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
||||
|
@ -170,26 +170,26 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
}
|
||||
|
||||
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("&[u8]")
|
||||
unsupported!("&[u8]")
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("None")
|
||||
unsupported!("None")
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
unsupported("Some")
|
||||
unsupported!("Some")
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("()")
|
||||
unsupported!("()")
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("unit struct")
|
||||
unsupported!("unit struct")
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
|
@ -198,7 +198,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
unsupported("unit variant")
|
||||
unsupported!("unit variant")
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
|
@ -209,7 +209,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
unsupported("newtype struct")
|
||||
unsupported!("newtype struct")
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
|
@ -232,7 +232,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
(crate::ARRAY_ENUM_NAME, crate::LONG_ARRAY_VARIANT_NAME) => {
|
||||
(Tag::LongArray, ArrayType::Long)
|
||||
}
|
||||
_ => return unsupported("newtype variant"),
|
||||
_ => return unsupported!("newtype variant"),
|
||||
};
|
||||
|
||||
self.check_state(array_tag)?;
|
||||
|
@ -247,7 +247,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
if let State::Array(array_type) = self.state {
|
||||
let len = match len {
|
||||
Some(len) => len,
|
||||
None => return Err(Error(anyhow!("array length must be known up front"))),
|
||||
None => return Err(Error::new_static("array length must be known up front")),
|
||||
};
|
||||
|
||||
match len.try_into() {
|
||||
|
@ -259,25 +259,25 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
len,
|
||||
))
|
||||
}
|
||||
Err(_) => Err(Error(anyhow!("length of array exceeds i32::MAX"))),
|
||||
Err(_) => Err(Error::new_static("length of array exceeds i32::MAX")),
|
||||
}
|
||||
} else {
|
||||
self.check_state(Tag::List)?;
|
||||
|
||||
let len = match len {
|
||||
Some(len) => len,
|
||||
None => return Err(Error(anyhow!("list length must be known up front"))),
|
||||
None => return Err(Error::new_static("list length must be known up front")),
|
||||
};
|
||||
|
||||
match len.try_into() {
|
||||
Ok(len) => Ok(SerializeSeq::list(self.writer, len)),
|
||||
Err(_) => Err(Error(anyhow!("length of list exceeds i32::MAX"))),
|
||||
Err(_) => Err(Error::new_static("length of list exceeds i32::MAX")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||
unsupported("tuple")
|
||||
unsupported!("tuple")
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
|
@ -285,7 +285,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
_name: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
unsupported("tuple struct")
|
||||
unsupported!("tuple struct")
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(
|
||||
|
@ -295,7 +295,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
unsupported("tuple variant")
|
||||
unsupported!("tuple variant")
|
||||
}
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
|
@ -325,7 +325,7 @@ impl<'a, W: Write + ?Sized> Serializer for &'a mut PayloadSerializer<'_, '_, W>
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
unsupported("struct variant")
|
||||
unsupported!("struct variant")
|
||||
}
|
||||
|
||||
fn is_human_readable(&self) -> bool {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::WriteBytesExt;
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
|
@ -26,10 +25,14 @@ impl<'n, W: Write> RootSerializer<'n, W> {
|
|||
}
|
||||
}
|
||||
|
||||
fn not_compound<T>(typ: &str) -> Result<T, Error> {
|
||||
Err(Error(anyhow!(
|
||||
"root value must be a map or struct (got {typ})"
|
||||
)))
|
||||
macro_rules! not_compound {
|
||||
($typ:literal) => {
|
||||
Err(Error::new_static(concat!(
|
||||
"root value must be a map or struct (got ",
|
||||
$typ,
|
||||
")"
|
||||
)))
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
||||
|
@ -44,78 +47,78 @@ impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
|||
type SerializeStructVariant = Impossible;
|
||||
|
||||
fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("bool")
|
||||
not_compound!("bool")
|
||||
}
|
||||
|
||||
fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("i8")
|
||||
not_compound!("i8")
|
||||
}
|
||||
|
||||
fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("i16")
|
||||
not_compound!("i16")
|
||||
}
|
||||
|
||||
fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("i32")
|
||||
not_compound!("i32")
|
||||
}
|
||||
|
||||
fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("i64")
|
||||
not_compound!("i64")
|
||||
}
|
||||
|
||||
fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("u8")
|
||||
not_compound!("u8")
|
||||
}
|
||||
|
||||
fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("u16")
|
||||
not_compound!("u16")
|
||||
}
|
||||
|
||||
fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("u32")
|
||||
not_compound!("u32")
|
||||
}
|
||||
|
||||
fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("u64")
|
||||
not_compound!("u64")
|
||||
}
|
||||
|
||||
fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("f32")
|
||||
not_compound!("f32")
|
||||
}
|
||||
|
||||
fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("f64")
|
||||
not_compound!("f64")
|
||||
}
|
||||
|
||||
fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("char")
|
||||
not_compound!("char")
|
||||
}
|
||||
|
||||
fn serialize_str(self, _v: &str) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("str")
|
||||
not_compound!("str")
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("&[u8]")
|
||||
not_compound!("&[u8]")
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("None")
|
||||
not_compound!("None")
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
not_compound("Some")
|
||||
not_compound!("Some")
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("()")
|
||||
not_compound!("()")
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("unit struct")
|
||||
not_compound!("unit struct")
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
|
@ -124,7 +127,7 @@ impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
|||
_variant_index: u32,
|
||||
_variant: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
not_compound("unit variant")
|
||||
not_compound!("unit variant")
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
|
@ -135,7 +138,7 @@ impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
not_compound("newtype struct")
|
||||
not_compound!("newtype struct")
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
|
@ -148,15 +151,15 @@ impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
|||
where
|
||||
T: Serialize,
|
||||
{
|
||||
not_compound("newtype variant")
|
||||
not_compound!("newtype variant")
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
not_compound("seq")
|
||||
not_compound!("seq")
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||
not_compound("tuple")
|
||||
not_compound!("tuple")
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
|
@ -164,7 +167,7 @@ impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
|||
_name: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
not_compound("tuple struct")
|
||||
not_compound!("tuple struct")
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(
|
||||
|
@ -174,7 +177,7 @@ impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
not_compound("tuple variant")
|
||||
not_compound!("tuple variant")
|
||||
}
|
||||
|
||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
|
@ -204,7 +207,7 @@ impl<'a, W: Write> Serializer for &'a mut RootSerializer<'_, W> {
|
|||
_variant: &'static str,
|
||||
_len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
not_compound("struct variant")
|
||||
not_compound!("struct variant")
|
||||
}
|
||||
|
||||
fn is_human_readable(&self) -> bool {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::io::Write;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use serde::{ser, Serialize};
|
||||
|
||||
|
@ -58,7 +57,7 @@ impl<W: Write + ?Sized> ser::SerializeSeq for SerializeSeq<'_, W> {
|
|||
T: Serialize,
|
||||
{
|
||||
if self.remaining <= 0 {
|
||||
return Err(Error(anyhow!(
|
||||
return Err(Error::new_owned(format!(
|
||||
"attempt to serialize more {} elements than specified",
|
||||
self.list_or_array.name()
|
||||
)));
|
||||
|
@ -94,10 +93,10 @@ impl<W: Write + ?Sized> ser::SerializeSeq for SerializeSeq<'_, W> {
|
|||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
if self.remaining > 0 {
|
||||
return Err(Error(anyhow!(
|
||||
return Err(Error::new_owned(format!(
|
||||
"{} {} element(s) left to serialize",
|
||||
self.remaining,
|
||||
self.list_or_array.name(),
|
||||
self.list_or_array.name()
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ impl<W: Write + ?Sized> ser::SerializeStruct for SerializeStruct<'_, W> {
|
|||
{
|
||||
value
|
||||
.serialize(&mut PayloadSerializer::named(self.writer, key))
|
||||
.map_err(|e| e.context(format!("field `{key}`")))
|
||||
.map_err(|e| e.field(key))
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
|
|
|
@ -1,31 +1,94 @@
|
|||
use std::error::Error as StdError;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io;
|
||||
use std::fmt::Display;
|
||||
use std::iter::FusedIterator;
|
||||
use std::{fmt, io};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use serde::{de, ser};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Error(pub(super) anyhow::Error);
|
||||
pub struct Error {
|
||||
/// Box this to keep the error as small as possible. We don't want to
|
||||
/// slow down the common case where no error occurs.
|
||||
inner: Box<ErrorInner>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ErrorInner {
|
||||
path: Vec<String>,
|
||||
cause: Cause,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Cause {
|
||||
Io(io::Error),
|
||||
// catch-all errors
|
||||
Owned(Box<str>),
|
||||
Static(&'static str),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub(super) fn context<C>(self, ctx: C) -> Self
|
||||
where
|
||||
C: Display + Send + Sync + 'static,
|
||||
pub(crate) fn new_owned(msg: impl Into<Box<str>>) -> Self {
|
||||
Self {
|
||||
inner: Box::new(ErrorInner {
|
||||
path: Vec::new(),
|
||||
cause: Cause::Owned(msg.into()),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_static(msg: &'static str) -> Self {
|
||||
Self {
|
||||
inner: Box::new(ErrorInner {
|
||||
path: Vec::new(),
|
||||
cause: Cause::Static(msg),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn field(mut self, ctx: impl Into<String>) -> Self {
|
||||
self.inner.path.push(ctx.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn path(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = &str> + ExactSizeIterator + FusedIterator + Clone + '_
|
||||
{
|
||||
Self(self.0.context(ctx))
|
||||
self.inner.path.iter().rev().map(|s| s.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let len = self.inner.path.len();
|
||||
|
||||
if len > 0 {
|
||||
write!(f, "(")?;
|
||||
for (i, ctx) in self.path().enumerate() {
|
||||
write!(f, "{ctx}")?;
|
||||
|
||||
if i != len - 1 {
|
||||
write!(f, " → ")?;
|
||||
}
|
||||
}
|
||||
write!(f, ") ")?;
|
||||
}
|
||||
|
||||
match &self.inner.cause {
|
||||
Cause::Io(e) => e.fmt(f),
|
||||
Cause::Owned(s) => write!(f, "{s}"),
|
||||
Cause::Static(s) => write!(f, "{s}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for Error {
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
self.0.source()
|
||||
match &self.inner.cause {
|
||||
Cause::Io(e) => Some(e),
|
||||
Cause::Owned(_) => None,
|
||||
Cause::Static(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +97,7 @@ impl ser::Error for Error {
|
|||
where
|
||||
T: Display,
|
||||
{
|
||||
Error(anyhow!("{msg}"))
|
||||
Error::new_owned(format!("{msg}"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,12 +106,17 @@ impl de::Error for Error {
|
|||
where
|
||||
T: Display,
|
||||
{
|
||||
Error(anyhow!("{msg}"))
|
||||
Error::new_owned(format!("{msg}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(e: io::Error) -> Self {
|
||||
Error(anyhow::Error::new(e))
|
||||
Self {
|
||||
inner: Box::new(ErrorInner {
|
||||
path: Vec::new(),
|
||||
cause: Cause::Io(e),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use anyhow::anyhow;
|
||||
pub use array::*;
|
||||
pub use error::*;
|
||||
use serde::de::Visitor;
|
||||
|
@ -119,7 +118,7 @@ impl Tag {
|
|||
10 => Ok(Tag::Compound),
|
||||
11 => Ok(Tag::IntArray),
|
||||
12 => Ok(Tag::LongArray),
|
||||
_ => Err(Error(anyhow!("invalid tag byte `{id}`"))),
|
||||
_ => Err(Error::new_owned(format!("invalid tag byte `{id}`"))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,6 +145,8 @@ impl Display for Tag {
|
|||
}
|
||||
}
|
||||
|
||||
const CESU8_DECODE_ERROR: &str = "could not convert CESU-8 data to UTF-8";
|
||||
|
||||
const ARRAY_ENUM_NAME: &str = "__array__";
|
||||
|
||||
const BYTE_ARRAY_VARIANT_NAME: &str = "__byte_array__";
|
||||
|
|
Loading…
Add table
Reference in a new issue