mod deserialize;
mod intermediate;
mod map;
mod serialize;
mod update;
use std::{
borrow::Cow,
collections::LinkedList,
fmt::{self, Display, Formatter},
};
#[cfg(feature = "derive")]
pub use serde_lite_derive::{Deserialize, Serialize, Update};
pub use crate::{
deserialize::Deserialize,
intermediate::{Intermediate, Number},
map::{Map, MapImpl},
serialize::Serialize,
update::Update,
};
#[derive(Debug, Clone)]
pub enum Error {
OutOfBounds,
UnsupportedConversion,
MissingField,
UnknownEnumVariant,
MissingEnumVariantContent,
InvalidValue(Cow<'static, str>),
NamedFieldErrors(ErrorList<NamedFieldError>),
UnnamedFieldErrors(ErrorList<UnnamedFieldError>),
Custom(Cow<'static, str>),
}
impl Error {
#[inline]
pub fn invalid_value<T>(expected: T) -> Self
where
T: ToString,
{
Self::InvalidValue(Cow::Owned(expected.to_string()))
}
#[inline]
pub const fn invalid_value_static(expected: &'static str) -> Self {
Self::InvalidValue(Cow::Borrowed(expected))
}
#[inline]
pub fn custom<T>(msg: T) -> Self
where
T: ToString,
{
Self::Custom(Cow::Owned(msg.to_string()))
}
#[inline]
pub const fn custom_static(msg: &'static str) -> Self {
Self::Custom(Cow::Borrowed(msg))
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::OutOfBounds => f.write_str("value is out of bounds"),
Self::UnsupportedConversion => f.write_str("conversion not supported"),
Self::MissingField => f.write_str("missing field"),
Self::UnknownEnumVariant => f.write_str("unknown enum variant"),
Self::MissingEnumVariantContent => f.write_str("missing enum variant content"),
Self::InvalidValue(expected) => write!(f, "invalid value ({} expected)", expected),
Self::NamedFieldErrors(errors) => {
write!(f, "field errors ({})", errors)
}
Self::UnnamedFieldErrors(errors) => {
write!(f, "field errors ({})", errors)
}
Self::Custom(msg) => f.write_str(msg),
}
}
}
impl std::error::Error for Error {}
impl From<ErrorList<NamedFieldError>> for Error {
#[inline]
fn from(errors: ErrorList<NamedFieldError>) -> Self {
Self::NamedFieldErrors(errors)
}
}
impl From<NamedFieldError> for Error {
#[inline]
fn from(err: NamedFieldError) -> Self {
let mut errors = ErrorList::new();
errors.push(err);
Self::from(errors)
}
}
impl From<ErrorList<UnnamedFieldError>> for Error {
#[inline]
fn from(errors: ErrorList<UnnamedFieldError>) -> Self {
Self::UnnamedFieldErrors(errors)
}
}
impl From<UnnamedFieldError> for Error {
#[inline]
fn from(err: UnnamedFieldError) -> Self {
let mut errors = ErrorList::new();
errors.push(err);
Self::from(errors)
}
}
#[derive(Debug, Clone)]
pub struct NamedFieldError {
field: Cow<'static, str>,
error: Error,
}
impl NamedFieldError {
#[inline]
pub fn new<T>(field: T, error: Error) -> Self
where
T: ToString,
{
Self {
field: Cow::Owned(field.to_string()),
error,
}
}
#[inline]
pub const fn new_static(field: &'static str, error: Error) -> Self {
Self {
field: Cow::Borrowed(field),
error,
}
}
#[inline]
pub fn field(&self) -> &str {
&self.field
}
#[inline]
pub fn error(&self) -> &Error {
&self.error
}
#[inline]
pub fn into_error(self) -> Error {
self.error
}
}
impl Display for NamedFieldError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}: {}", self.field, self.error)
}
}
impl std::error::Error for NamedFieldError {}
#[derive(Debug, Clone)]
pub struct UnnamedFieldError {
index: usize,
error: Error,
}
impl UnnamedFieldError {
#[inline]
pub const fn new(field_index: usize, error: Error) -> Self {
Self {
index: field_index,
error,
}
}
#[inline]
pub fn field_index(&self) -> usize {
self.index
}
#[inline]
pub fn error(&self) -> &Error {
&self.error
}
#[inline]
pub fn into_error(self) -> Error {
self.error
}
}
impl Display for UnnamedFieldError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}: {}", self.index, self.error)
}
}
impl std::error::Error for UnnamedFieldError {}
#[derive(Debug, Clone)]
pub struct ErrorList<T> {
inner: LinkedList<T>,
}
impl<T> ErrorList<T> {
#[inline]
pub const fn new() -> Self {
Self {
inner: LinkedList::new(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn push(&mut self, err: T) {
self.inner.push_back(err)
}
#[inline]
pub fn append(&mut self, mut other: Self) {
self.inner.append(&mut other.inner)
}
#[inline]
pub fn iter(&self) -> std::collections::linked_list::Iter<'_, T> {
self.inner.iter()
}
}
impl<T> Default for ErrorList<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<'a, T> IntoIterator for &'a ErrorList<T> {
type Item = &'a T;
type IntoIter = std::collections::linked_list::Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.inner.iter()
}
}
impl<T> IntoIterator for ErrorList<T> {
type Item = T;
type IntoIter = std::collections::linked_list::IntoIter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl<T> Display for ErrorList<T>
where
T: Display,
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let mut iter = self.iter();
if let Some(first) = iter.next() {
Display::fmt(first, f)?;
}
for err in iter {
write!(f, ", {}", err)?;
}
Ok(())
}
}
impl<T> std::error::Error for ErrorList<T> where T: std::error::Error {}