use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Deserializer};
use serde::de::Visitor;
use rmpv::ValueRef;
use rmpv::ext::EnumRefDeserializer;
#[derive(Clone, Debug, Deserialize)]
pub struct Error {
error: (i64, i64),
description: Option<String>,
}
impl Error {
pub fn new(category: i64, code: i64, description: Option<String>) -> Self {
Self {
error: (category, code),
description: description,
}
}
pub fn category(&self) -> i64 {
self.error.0
}
pub fn code(&self) -> i64 {
self.error.1
}
pub fn description(&self) -> Option<&str> {
self.description.as_ref().map(|v| v.as_str())
}
pub fn into_description(self) -> Option<String> {
self.description
}
}
impl Display for Error {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
let desc = self.description.as_ref().map(|s| s.as_str()).unwrap_or("no description");
write!(fmt, "[{}]: {}", self.code(), desc)
}
}
impl Into<super::Error> for Error {
fn into(self) -> super::Error {
super::Error::Service(self)
}
}
pub type Primitive<T> = Result<T, Error>;
#[derive(Debug, Deserialize)]
pub enum Streaming<T> {
Write(T),
Error(Error),
Close,
}
pub trait Flatten {
type Item;
fn flatten(self) -> Result<Self::Item, super::Error>;
}
impl<T, E> Flatten for Result<Result<T, E>, super::Error>
where E: Into<super::Error>
{
type Item = T;
fn flatten(self) -> Result<Self::Item, super::Error> {
match self {
Ok(Ok(v)) => Ok(v),
Ok(Err(err)) => Err(err.into()),
Err(err) => Err(err),
}
}
}
impl<T> Flatten for Result<Streaming<T>, super::Error> {
type Item = Option<T>;
fn flatten(self) -> Result<Self::Item, super::Error> {
match self {
Ok(Streaming::Write(v)) => Ok(Some(v)),
Ok(Streaming::Error(e)) => Err(e.into()),
Ok(Streaming::Close) => Ok(None),
Err(err) => Err(err),
}
}
}
struct PackedValue<'a>(u64, &'a ValueRef<'a>);
impl<'de> Deserializer<'de> for PackedValue<'de> {
type Error = super::Error;
#[inline]
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
unimplemented!();
}
#[inline]
fn deserialize_enum<V>(self, _name: &'static str, variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
let PackedValue(ty, value) = self;
if ty < variants.len() as u64 {
let de = EnumRefDeserializer::new(ty as u32, Some(value));
visitor.visit_enum(de)
.map_err(|err| super::Error::InvalidDataFraming(format!("{}", err)))
} else {
Err(super::Error::InvalidDataFraming(format!("unexpected message with type {}", ty)))
}
}
forward_to_deserialize_any! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit
tuple seq bytes byte_buf map option
unit_struct tuple_struct struct newtype_struct identifier ignored_any
}
}
pub fn deserialize<'de, D: Deserialize<'de>>(ty: u64, args: &'de ValueRef<'de>) -> Result<D, super::Error> {
Deserialize::deserialize(PackedValue(ty, args))
}