use core::str::from_utf8;
pub mod prelude {
#[cfg(feature = "serde-bson")]
pub extern crate bson;
#[cfg(feature = "serde-flexbuffers")]
pub extern crate flexbuffers;
#[cfg(feature = "serde-json5")]
pub extern crate json5;
#[cfg(feature = "serde-postcard")]
pub extern crate postcard;
#[cfg(feature = "serde-messagepack")]
pub extern crate rmp_serde as messagepack;
#[cfg(feature = "serde-ron")]
pub extern crate ron;
#[cfg(feature = "serde-cbor")]
pub extern crate serde_cbor as cbor;
pub extern crate serde_derive;
#[cfg(feature = "serde-json")]
pub extern crate serde_json as json;
#[cfg(feature = "serde-lexpr")]
pub extern crate serde_lexpr as lexpr;
#[cfg(feature = "serde-pickle")]
pub extern crate serde_pickle as pickle;
#[cfg(feature = "serde-query-string")]
pub extern crate serde_qs as qs;
#[cfg(feature = "serde-accept-limited-xml-serialize")]
pub extern crate serde_xml_rs as xml;
#[cfg(feature = "serde-yaml")]
pub extern crate serde_yaml as yaml;
}
use core::convert::{Infallible, Into, TryFrom, TryInto};
use core::ops::{Deref, DerefMut};
use core::str::Utf8Error;
#[cfg(feature = "serde-ron")]
use ron::de::SpannedError;
use serde::de::DeserializeOwned;
use serde::Serialize;
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::fmt::*;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(PartialEq, Eq, Debug)]
pub enum ContentType {
#[cfg(feature = "serde-bson")]
Bson,
#[cfg(feature = "serde-cbor")]
Cbor,
#[cfg(feature = "serde-flexbuffers")]
FlexBuffers,
#[cfg(feature = "serde-json")]
Json,
#[cfg(feature = "serde-json5")]
Json5,
#[cfg(feature = "serde-lexpr")]
Lexpr,
#[cfg(feature = "serde-messagepack")]
MessagePack,
#[cfg(feature = "serde-pickle")]
Pickle,
#[cfg(feature = "serde-postcard")]
Postcard,
#[cfg(feature = "serde-ron")]
Ron,
#[cfg(feature = "serde-toml")]
Toml,
#[cfg(feature = "serde-query-string")]
QueryString,
#[cfg(feature = "serde-yaml")]
Yaml,
#[cfg(feature = "serde-accept-limited-xml-serialize")]
Xml,
}
impl TryFrom<&str> for ContentType {
type Error = Error;
fn try_from(s: &str) -> core::result::Result<ContentType, Self::Error> {
#[allow(unreachable_patterns)]
match s.to_lowercase().as_str() {
#[cfg(feature = "serde-bson")]
"bson" => Ok(ContentType::Bson),
#[cfg(feature = "serde-bson")]
"application/bson" => Ok(ContentType::Bson),
#[cfg(feature = "serde-bson")]
"application/x-bson" => Ok(ContentType::Bson),
#[cfg(feature = "serde-cbor")]
"cbor" => Ok(ContentType::Cbor),
#[cfg(feature = "serde-cbor")]
"application/cbor" => Ok(ContentType::Cbor),
#[cfg(feature = "serde-cbor")]
"application/x-cbor" => Ok(ContentType::Cbor),
#[cfg(feature = "serde-flexbuffers")]
"flexbuffers" => Ok(ContentType::FlexBuffers),
#[cfg(feature = "serde-flexbuffers")]
"application/flexbuffers" => Ok(ContentType::FlexBuffers),
#[cfg(feature = "serde-flexbuffers")]
"application/x-flexbuffers" => Ok(ContentType::FlexBuffers),
#[cfg(feature = "serde-json")]
"json" => Ok(ContentType::Json),
#[cfg(feature = "serde-json")]
"application/json" => Ok(ContentType::Json),
#[cfg(feature = "serde-json")]
"application/x-json" => Ok(ContentType::Json),
#[cfg(feature = "serde-json5")]
"json5" => Ok(ContentType::Json5),
#[cfg(feature = "serde-json5")]
"application/json5" => Ok(ContentType::Json5),
#[cfg(feature = "serde-json5")]
"application/x-json5" => Ok(ContentType::Json5),
#[cfg(feature = "serde-lexpr")]
"lexpr" => Ok(ContentType::Lexpr),
#[cfg(feature = "serde-lexpr")]
"application/lexpr" => Ok(ContentType::Lexpr),
#[cfg(feature = "serde-lexpr")]
"application/x-lexpr" => Ok(ContentType::Lexpr),
#[cfg(feature = "serde-messagepack")]
"messagepack" => Ok(ContentType::MessagePack),
#[cfg(feature = "serde-messagepack")]
"application/messagepack" => Ok(ContentType::MessagePack),
#[cfg(feature = "serde-messagepack")]
"application/x-messagepack" => Ok(ContentType::MessagePack),
#[cfg(feature = "serde-pickle")]
"pickle" => Ok(ContentType::Pickle),
#[cfg(feature = "serde-pickle")]
"application/pickle" => Ok(ContentType::Pickle),
#[cfg(feature = "serde-pickle")]
"application/x-pickle" => Ok(ContentType::Pickle),
#[cfg(feature = "serde-postcard")]
"postcard" => Ok(ContentType::Postcard),
#[cfg(feature = "serde-postcard")]
"application/postcard" => Ok(ContentType::Postcard),
#[cfg(feature = "serde-postcard")]
"application/x-postcard" => Ok(ContentType::Postcard),
#[cfg(feature = "serde-ron")]
"ron" => Ok(ContentType::Ron),
#[cfg(feature = "serde-ron")]
"application/ron" => Ok(ContentType::Ron),
#[cfg(feature = "serde-ron")]
"application/x-ron" => Ok(ContentType::Ron),
#[cfg(feature = "serde-toml")]
"toml" => Ok(ContentType::Toml),
#[cfg(feature = "serde-toml")]
"application/toml" => Ok(ContentType::Toml),
#[cfg(feature = "serde-toml")]
"application/x-toml" => Ok(ContentType::Toml),
#[cfg(feature = "serde-query-string")]
"querystring" => Ok(ContentType::QueryString),
#[cfg(feature = "serde-query-string")]
"application/querystring" => Ok(ContentType::QueryString),
#[cfg(feature = "serde-query-string")]
"application/x-querystring" => Ok(ContentType::QueryString),
#[cfg(feature = "serde-yaml")]
"yaml" => Ok(ContentType::Yaml),
#[cfg(feature = "serde-yaml")]
"application/yaml" => Ok(ContentType::Yaml),
#[cfg(feature = "serde-yaml")]
"application/x-yaml" => Ok(ContentType::Yaml),
#[cfg(feature = "serde-accept-limited-xml-serialize")]
"xml" => Ok(ContentType::Xml),
#[cfg(feature = "serde-accept-limited-xml-serialize")]
"application/xml" => Ok(ContentType::Xml),
#[cfg(feature = "serde-accept-limited-xml-serialize")]
"application/x-xml" => Ok(ContentType::Xml),
_ => Err(Error::UnknownContentTypeMatchFromStr(s.to_string())),
}
}
}
impl TryFrom<String> for ContentType {
type Error = Error;
fn try_from(s: String) -> core::result::Result<ContentType, Self::Error> {
Self::try_from(s.as_str())
}
}
impl TryFrom<&String> for ContentType {
type Error = Error;
fn try_from(s: &String) -> core::result::Result<ContentType, Self::Error> {
Self::try_from(s.as_str())
}
}
impl TryFrom<&ContentType> for ContentType {
type Error = Error;
fn try_from(h: &ContentType) -> core::result::Result<ContentType, Self::Error> {
match h {
#[cfg(feature = "serde-bson")]
Self::Bson => Ok(Self::Bson),
#[cfg(feature = "serde-cbor")]
Self::Cbor => Ok(Self::Cbor),
#[cfg(feature = "serde-flexbuffers")]
Self::FlexBuffers => Ok(Self::FlexBuffers),
#[cfg(feature = "serde-json")]
Self::Json => Ok(Self::Json),
#[cfg(feature = "serde-json5")]
Self::Json5 => Ok(Self::Json5),
#[cfg(feature = "serde-lexpr")]
Self::Lexpr => Ok(Self::Lexpr),
#[cfg(feature = "serde-messagepack")]
Self::MessagePack => Ok(Self::MessagePack),
#[cfg(feature = "serde-pickle")]
Self::Pickle => Ok(Self::Pickle),
#[cfg(feature = "serde-postcard")]
Self::Postcard => Ok(Self::Postcard),
#[cfg(feature = "serde-ron")]
Self::Ron => Ok(Self::Ron),
#[cfg(feature = "serde-toml")]
Self::Toml => Ok(Self::Toml),
#[cfg(feature = "serde-query-string")]
Self::QueryString => Ok(Self::QueryString),
#[cfg(feature = "serde-yaml")]
Self::Yaml => Ok(Self::Yaml),
#[cfg(feature = "serde-accept-limited-xml-serialize")]
Self::Xml => Ok(Self::Xml),
_ => Err(Self::Error::NoSerializersDeserializersSet),
}
}
}
#[derive(Debug, Display)]
pub enum Error {
#[display(fmt = "Infallible - This error should have been infallible")]
Infallible,
#[display(fmt = "Converting Raw Data to UTF8 failed: {}", _0)]
ByteToUTF8ConversionFailure(Utf8Error),
#[display(fmt = "Unknown content type match from str: {}", _0)]
UnknownContentTypeMatchFromStr(String),
#[cfg(feature = "serde-bson")]
#[display(fmt = "BSON encoder/decoder error: {}", _0)]
BsonSerializationFailure(bson::ser::Error),
#[cfg(feature = "serde-bson")]
#[display(fmt = "BSON encode/decoder error: {}", _0)]
BsonDeserializationFailure(bson::de::Error),
#[cfg(feature = "serde-cbor")]
#[display(fmt = "CBOR encoder/decoder error: {}", _0)]
CborFailure(serde_cbor::Error),
#[cfg(feature = "serde-flexbuffers")]
#[display(fmt = "Flexbuffers encoder/decoder error: {}", _0)]
FlexBuffersSerializationFailure(flexbuffers::SerializationError),
#[cfg(feature = "serde-flexbuffers")]
#[display(fmt = "Flexbuffers encoder/decoder error: {}", _0)]
FlexBuffersDeserializationFailure(flexbuffers::DeserializationError),
#[cfg(feature = "serde-json")]
#[display(fmt = "JSON encoder/decoder error: {}", _0)]
JsonError(serde_json::Error),
#[cfg(feature = "serde-json5")]
#[display(fmt = "JSON5 encoder/decoder error: {}", _0)]
Json5Error(json5::Error),
#[cfg(feature = "serde-lexpr")]
#[display(fmt = "LEXPR encoder/decoder error: {}", _0)]
LexprError(serde_lexpr::Error),
#[cfg(feature = "serde-messagepack")]
#[display(fmt = "MessagePack encoder/decoder error: {}", _0)]
MessagePackEncodeError(rmp_serde::encode::Error),
#[cfg(feature = "serde-messagepack")]
#[display(fmt = "MessagePack encoder/decoder error: {}", _0)]
MessagePackDecodeError(rmp_serde::decode::Error),
#[cfg(feature = "serde-pickle")]
#[display(fmt = "Pickle encoder/decoder error: {}", _0)]
PickleError(serde_pickle::Error),
#[cfg(feature = "serde-postcard")]
#[display(fmt = "Postcard encoder/decoder error: {}", _0)]
PostcardError(postcard::Error),
#[cfg(feature = "serde-ron")]
#[display(fmt = "RON encoder/decoder error: {}", _0)]
RonError(ron::Error),
#[cfg(feature = "serde-ron")]
#[display(fmt = "RON decoder error: {}", _0)]
RonDecodeError(ron::de::SpannedError),
#[cfg(feature = "serde-toml")]
#[display(fmt = "TOML encoder/decoder error: {}", _0)]
TomlSerializationFailure(toml::ser::Error),
#[cfg(feature = "serde-toml")]
#[display(fmt = "TOML encoder/decoder error: {}", _0)]
TomlDeserializationFailure(toml::de::Error),
#[cfg(feature = "serde-query-string")]
#[display(fmt = "URL encoder/decoder error: {}", _0)]
QueryStringEncodingFailure(serde_qs::Error),
#[cfg(feature = "serde-yaml")]
#[display(fmt = "YAML encoder/decoder error: {}", _0)]
YamlError(serde_yaml::Error),
#[cfg(feature = "serde-accept-limited-xml-serialize")]
#[display(fmt = "XML encoder/decoder error: {}", _0)]
XmlError(prelude::xml::Error),
#[display(fmt = "Type is not supported for encoding/decoding: {:?}", _0)]
TypeDoesNotSupportSerialization(ContentType),
#[display(fmt = "This would only happen if no serializers/deserializers have been set")]
NoSerializersDeserializersSet,
}
impl From<Infallible> for Error {
fn from(_: Infallible) -> Self {
Error::Infallible
}
}
impl From<Utf8Error> for Error {
fn from(e: Utf8Error) -> Self {
Error::ByteToUTF8ConversionFailure(e)
}
}
#[cfg(feature = "serde-bson")]
impl From<bson::ser::Error> for Error {
fn from(e: bson::ser::Error) -> Self {
Error::BsonSerializationFailure(e)
}
}
#[cfg(feature = "serde-bson")]
impl From<bson::de::Error> for Error {
fn from(e: bson::de::Error) -> Self {
Error::BsonDeserializationFailure(e)
}
}
#[cfg(feature = "serde-cbor")]
impl From<serde_cbor::Error> for Error {
fn from(e: serde_cbor::Error) -> Self {
Error::CborFailure(e)
}
}
#[cfg(feature = "serde-flexbuffers")]
impl From<flexbuffers::SerializationError> for Error {
fn from(e: flexbuffers::SerializationError) -> Self {
Error::FlexBuffersSerializationFailure(e)
}
}
#[cfg(feature = "serde-flexbuffers")]
impl From<flexbuffers::DeserializationError> for Error {
fn from(e: flexbuffers::DeserializationError) -> Self {
Error::FlexBuffersDeserializationFailure(e)
}
}
#[cfg(feature = "serde-json")]
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::JsonError(e)
}
}
#[cfg(feature = "serde-json5")]
impl From<json5::Error> for Error {
fn from(e: json5::Error) -> Self {
Error::Json5Error(e)
}
}
#[cfg(feature = "serde-lexpr")]
impl From<serde_lexpr::Error> for Error {
fn from(e: serde_lexpr::Error) -> Self {
Error::LexprError(e)
}
}
#[cfg(feature = "serde-messagepack")]
impl From<rmp_serde::encode::Error> for Error {
fn from(e: rmp_serde::encode::Error) -> Self {
Error::MessagePackEncodeError(e)
}
}
#[cfg(feature = "serde-messagepack")]
impl From<rmp_serde::decode::Error> for Error {
fn from(e: rmp_serde::decode::Error) -> Self {
Error::MessagePackDecodeError(e)
}
}
#[cfg(feature = "serde-pickle")]
impl From<serde_pickle::Error> for Error {
fn from(e: serde_pickle::Error) -> Self {
Error::PickleError(e)
}
}
#[cfg(feature = "serde-postcard")]
impl From<postcard::Error> for Error {
fn from(e: postcard::Error) -> Self {
Error::PostcardError(e)
}
}
#[cfg(feature = "serde-ron")]
impl From<ron::Error> for Error {
fn from(e: ron::Error) -> Self {
Error::RonError(e)
}
}
#[cfg(feature = "serde-toml")]
impl From<toml::ser::Error> for Error {
fn from(e: toml::ser::Error) -> Self {
Error::TomlSerializationFailure(e)
}
}
#[cfg(feature = "serde-toml")]
impl From<toml::de::Error> for Error {
fn from(e: toml::de::Error) -> Self {
Error::TomlDeserializationFailure(e)
}
}
#[cfg(feature = "serde-query-string")]
impl From<serde_qs::Error> for Error {
fn from(e: serde_qs::Error) -> Self {
Error::QueryStringEncodingFailure(e)
}
}
#[cfg(feature = "serde-yaml")]
impl From<serde_yaml::Error> for Error {
fn from(e: serde_yaml::Error) -> Self {
Error::YamlError(e)
}
}
#[cfg(feature = "serde-accept-limited-xml-serialize")]
impl From<prelude::xml::Error> for Error {
fn from(e: prelude::xml::Error) -> Self {
Error::XmlError(e)
}
}
#[cfg(feature = "serde-ron")]
impl From<ron::de::SpannedError> for Error {
fn from(e: ron::de::SpannedError) -> Self {
Self::RonDecodeError(e)
}
}
pub trait TryToString {
type Error;
fn try_to_string(&self) -> core::result::Result<String, Self::Error>;
}
pub trait SimpleEncoder
where
Self: serde::Serialize,
{
fn encode<F: TryInto<ContentType, Error = impl Into<Error>>>(
&self,
content_type: F,
) -> Result<Encoded>;
}
impl<T> SimpleEncoder for T
where
T: Serialize,
{
fn encode<F: TryInto<ContentType, Error = impl Into<Error>>>(
&self,
content_type: F,
) -> Result<Encoded> {
#[cfg(feature = "serde-bson")]
let bson = |o: &T| -> Result<Encoded> { bson::to_vec(o).try_into() };
#[cfg(feature = "serde-cbor")]
let cbor = |o: &T| -> Result<Encoded> { serde_cbor::to_vec(o).try_into() };
#[cfg(feature = "serde-flexbuffers")]
let flexbuffers = |o: &T| -> Result<Encoded> { flexbuffers::to_vec(o).try_into() };
#[cfg(feature = "serde-json")]
let json = |o: &T| -> Result<Encoded> { serde_json::to_vec(o).try_into() };
#[cfg(feature = "serde-json5")]
let json5 = |o: &T| -> Result<Encoded> { json5::to_string(o).try_into() };
#[cfg(feature = "serde-lexpr")]
let lexpr = |o: &T| -> Result<Encoded> { serde_lexpr::to_vec(o).try_into() };
#[cfg(feature = "serde-messagepack")]
let message_pack = |o: &T| -> Result<Encoded> { rmp_serde::to_vec(o).try_into() };
#[cfg(feature = "serde-pickle")]
let pickle =
|o: &T| -> Result<Encoded> { serde_pickle::to_vec(o, Default::default()).try_into() };
#[cfg(feature = "serde-postcard")]
let postcard = |o: &T| -> Result<Encoded> { postcard::to_allocvec(o).try_into() };
#[cfg(feature = "serde-ron")]
let ron = |o: &T| -> Result<Encoded> { ron::to_string(o).try_into() };
#[cfg(feature = "serde-toml")]
let toml = |o: &T| -> Result<Encoded> { toml::to_string(o).try_into() };
#[cfg(feature = "serde-query-string")]
let querystring = |o: &T| -> Result<Encoded> { serde_qs::to_string(o).try_into() };
#[cfg(feature = "serde-yaml")]
let yaml = |o: &T| -> Result<Encoded> { serde_yaml::to_string(o).try_into() };
#[cfg(feature = "serde-accept-limited-xml-serialize")]
let xml = |o: &T| -> Result<Encoded> { prelude::xml::to_string(o).try_into() };
match content_type.try_into().map_err(|e| e.into())? {
#[cfg(feature = "serde-bson")]
ContentType::Bson => bson(self),
#[cfg(feature = "serde-cbor")]
ContentType::Cbor => cbor(self),
#[cfg(feature = "serde-flexbuffers")]
ContentType::FlexBuffers => flexbuffers(self),
#[cfg(feature = "serde-json")]
ContentType::Json => json(self),
#[cfg(feature = "serde-json5")]
ContentType::Json5 => json5(self),
#[cfg(feature = "serde-lexpr")]
ContentType::Lexpr => lexpr(self),
#[cfg(feature = "serde-messagepack")]
ContentType::MessagePack => message_pack(self),
#[cfg(feature = "serde-pickle")]
ContentType::Pickle => pickle(self),
#[cfg(feature = "serde-postcard")]
ContentType::Postcard => postcard(self),
#[cfg(feature = "serde-ron")]
ContentType::Ron => ron(self),
#[cfg(feature = "serde-toml")]
ContentType::Toml => toml(self),
#[cfg(feature = "serde-query-string")]
ContentType::QueryString => querystring(self),
#[cfg(feature = "serde-yaml")]
ContentType::Yaml => yaml(self),
#[cfg(feature = "serde-accept-limited-xml-serialize")]
ContentType::Xml => xml(self),
}
}
}
pub trait SimpleDecoder<T> {
fn decode<F: TryInto<ContentType, Error = impl Into<Error>>>(
&self,
content_type: F,
) -> Result<T>;
}
impl<T> SimpleDecoder<Decoded<T>> for &[u8]
where
T: DeserializeOwned,
{
fn decode<F: TryInto<ContentType, Error = impl Into<Error>>>(
&self,
content_type: F,
) -> Result<Decoded<T>> {
#[cfg(feature = "serde-bson")]
let bson = |o: &[u8]| -> Result<Decoded<T>> { bson::from_slice(o).try_into() };
#[cfg(feature = "serde-cbor")]
let cbor = |o: &[u8]| -> Result<Decoded<T>> { serde_cbor::from_slice(o).try_into() };
#[cfg(feature = "serde-flexbuffers")]
let flexbuffers =
|o: &[u8]| -> Result<Decoded<T>> { flexbuffers::from_slice(o).try_into() };
#[cfg(feature = "serde-json")]
let json = |o: &[u8]| -> Result<Decoded<T>> { serde_json::from_slice(o).try_into() };
#[cfg(feature = "serde-json5")]
let json5 = |o: &[u8]| -> Result<Decoded<T>> {
from_utf8(o)
.map_err(Error::from)
.and_then(|str| json5::from_str(str).try_into())
};
#[cfg(feature = "serde-lexpr")]
let lexpr = |o: &[u8]| -> Result<Decoded<T>> { serde_lexpr::from_slice(o).try_into() };
#[cfg(feature = "serde-messagepack")]
let message_pack = |o: &[u8]| -> Result<Decoded<T>> { rmp_serde::from_slice(o).try_into() };
#[cfg(feature = "serde-pickle")]
let pickle = |o: &[u8]| -> Result<Decoded<T>> {
serde_pickle::from_slice(o, Default::default()).try_into()
};
#[cfg(feature = "serde-postcard")]
let postcard = |o: &[u8]| -> Result<Decoded<T>> { postcard::from_bytes(o).try_into() };
#[cfg(feature = "serde-ron")]
let ron = |o: &[u8]| -> Result<Decoded<T>> {
from_utf8(o)
.map_err(Error::from)
.and_then(|str| ron::from_str(str).try_into())
};
#[cfg(feature = "serde-toml")]
let toml = |o: &[u8]| -> Result<Decoded<T>> {
from_utf8(o)
.map_err(Error::from)
.and_then(|t| toml::from_str(t).try_into())
};
#[cfg(feature = "serde-query-string")]
let querystring = |o: &[u8]| -> Result<Decoded<T>> { serde_qs::from_bytes(o).try_into() };
#[cfg(feature = "serde-yaml")]
let yaml = |o: &[u8]| -> Result<Decoded<T>> { serde_yaml::from_slice(o).try_into() };
#[cfg(feature = "serde-accept-limited-xml-serialize")]
let xml = |o: &[u8]| -> Result<Decoded<T>> {
from_utf8(o)
.map_err(Error::from)
.and_then(|str| prelude::xml::de::from_str(str).try_into())
};
match content_type.try_into().map_err(|e| e.into())? {
#[cfg(feature = "serde-bson")]
ContentType::Bson => bson(self),
#[cfg(feature = "serde-cbor")]
ContentType::Cbor => cbor(self),
#[cfg(feature = "serde-flexbuffers")]
ContentType::FlexBuffers => flexbuffers(self),
#[cfg(feature = "serde-json")]
ContentType::Json => json(self),
#[cfg(feature = "serde-json5")]
ContentType::Json5 => json5(self),
#[cfg(feature = "serde-lexpr")]
ContentType::Lexpr => lexpr(self),
#[cfg(feature = "serde-messagepack")]
ContentType::MessagePack => message_pack(self),
#[cfg(feature = "serde-pickle")]
ContentType::Pickle => pickle(self),
#[cfg(feature = "serde-postcard")]
ContentType::Postcard => postcard(self),
#[cfg(feature = "serde-ron")]
ContentType::Ron => ron(self),
#[cfg(feature = "serde-toml")]
ContentType::Toml => toml(self),
#[cfg(feature = "serde-query-string")]
ContentType::QueryString => querystring(self),
#[cfg(feature = "serde-yaml")]
ContentType::Yaml => yaml(self),
#[cfg(feature = "serde-accept-limited-xml-serialize")]
ContentType::Xml => xml(self),
}
}
}
impl<T> SimpleDecoder<Decoded<T>> for Vec<u8>
where
T: DeserializeOwned,
{
fn decode<F: TryInto<ContentType, Error = impl Into<Error>>>(
&self,
content_type: F,
) -> Result<Decoded<T>> {
self.as_slice().decode(content_type)
}
}
impl<T> SimpleDecoder<Decoded<T>> for &str
where
T: DeserializeOwned,
{
fn decode<F: TryInto<ContentType, Error = impl Into<Error>>>(
&self,
content_type: F,
) -> Result<Decoded<T>> {
self.as_bytes().decode(content_type)
}
}
impl<T> SimpleDecoder<Decoded<T>> for String
where
T: DeserializeOwned,
{
fn decode<F: TryInto<ContentType, Error = impl Into<Error>>>(
&self,
content_type: F,
) -> Result<Decoded<T>> {
self.as_bytes().decode(content_type)
}
}
pub struct Encoded {
inner: Vec<u8>,
}
impl PartialEq<Self> for Encoded {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl PartialEq<String> for Encoded {
fn eq(&self, other: &String) -> bool {
if let Ok(self_string) = self.try_to_string() {
self_string == *other
} else {
false
}
}
}
impl PartialEq<&str> for Encoded {
fn eq(&self, other: &&str) -> bool {
if let Ok(self_string) = self.try_to_string() {
self_string == *other
} else {
false
}
}
}
impl Eq for Encoded {}
impl From<Vec<u8>> for Encoded {
fn from(v: Vec<u8>) -> Self {
Encoded { inner: v }
}
}
impl From<String> for Encoded {
fn from(s: String) -> Self {
Encoded {
inner: s.as_bytes().to_vec(),
}
}
}
impl From<&str> for Encoded {
fn from(s: &str) -> Self {
Encoded {
inner: s.as_bytes().to_vec(),
}
}
}
impl Deref for Encoded {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Encoded {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<E> TryFrom<core::result::Result<Vec<u8>, E>> for Encoded
where
E: Into<Error>,
{
type Error = Error;
fn try_from(
value: core::result::Result<Vec<u8>, E>,
) -> core::result::Result<Self, Self::Error> {
value.map(Encoded::from).map_err(|e| e.into())
}
}
impl<E> TryFrom<core::result::Result<String, E>> for Encoded
where
E: Into<Error>,
{
type Error = Error;
fn try_from(value: core::result::Result<String, E>) -> core::result::Result<Self, Self::Error> {
value.map(Encoded::from).map_err(|e| e.into())
}
}
impl<E> TryFrom<core::result::Result<&str, E>> for Encoded
where
E: Into<Error>,
{
type Error = Error;
fn try_from(value: core::result::Result<&str, E>) -> core::result::Result<Self, Self::Error> {
value.map(Encoded::from).map_err(|e| e.into())
}
}
impl TryToString for Encoded {
type Error = Error;
fn try_to_string(&self) -> core::result::Result<String, Self::Error> {
from_utf8(self).map_err(Error::from).map(|s| s.to_string())
}
}
pub struct Decoded<T>
where
T: DeserializeOwned,
{
pub(crate) inner: T,
}
impl<T, E> TryFrom<core::result::Result<T, E>> for Decoded<T>
where
T: DeserializeOwned,
E: Into<Error>,
{
type Error = Error;
fn try_from(res: core::result::Result<T, E>) -> core::result::Result<Self, Self::Error> {
res.map_err(|e| e.into()).map(Decoded::from)
}
}
impl<T: DeserializeOwned> From<T> for Decoded<T> {
fn from(t: T) -> Self {
Decoded { inner: t }
}
}
impl<T: DeserializeOwned> Deref for Decoded<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: DeserializeOwned> DerefMut for Decoded<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<T: DeserializeOwned> Decoded<T> {
pub fn into(self) -> T {
self.inner
}
}
#[cfg(test)]
mod test {
mod test_constants;
mod test_trait_impl;
use super::{ContentType, Decoded, Encoded, Error, SimpleDecoder, SimpleEncoder, TryToString};
use core::ops::Deref;
use serde::{Deserialize, Serialize};
use test_constants::*;
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct MyStruct {
unquoted: String,
#[serde(rename = "singleQuotes")]
single_quotes: String,
#[serde(rename = "lineBreaks")]
line_breaks: String,
hexadecimal: i32,
#[serde(rename = "leadingDecimalPoint")]
leading_decimal_point: f64,
#[serde(rename = "andTrailing")]
and_trailing: f64,
#[serde(rename = "positiveSign")]
positive_sign: i32,
#[serde(rename = "trailingComma")]
trailing_comma: String,
#[serde(rename = "andIn")]
and_in: Vec<String>,
#[serde(rename = "backwardsCompatible")]
backwards_compatible: String,
}
impl Default for MyStruct {
fn default() -> Self {
MyStruct {
unquoted: "and you can quote me on that".to_string(),
single_quotes: "I can use \"double quotes\" here".to_string(),
line_breaks: "Look, Mom! No \\n's!".to_string(),
hexadecimal: 0xdecaf,
leading_decimal_point: 0.8675309,
and_trailing: 8675309.0,
positive_sign: 1,
trailing_comma: "in objects".to_string(),
and_in: vec!["arrays".to_string(), "arrays-2".to_string()],
backwards_compatible: "with JSON".to_string(),
}
}
}
fn deserialize_test(ser_type: &str, compare_object: &[u8]) {
for i in ["", "application/", "application/x-"] {
let content_type = format!("{}{}", i, ser_type);
let my_struct: Decoded<MyStruct> = compare_object.decode(content_type).unwrap();
println!("Deserialize {} -> {:?}", ser_type, my_struct.deref());
assert_eq!(my_struct.into(), MyStruct::default());
}
}
fn serialize_test(ser_type: &str, compare_object: &[u8]) {
for i in ["", "application/", "application/x-"] {
let my_struct = MyStruct::default();
let serialized = my_struct.encode(format!("{}{}", i, ser_type)).unwrap();
if let Ok(s) = serialized.try_to_string() {
println!("Serialize {} -> {}", ser_type, s);
} else {
println!("Serialize {} -> {:?}", ser_type, serialized.deref());
}
if compare_object != serialized.deref() {
println!(
"Expected: {}",
String::from_utf8(compare_object.to_vec()).unwrap()
);
println!(
"Actual: {}",
String::from_utf8(serialized.deref().to_vec()).unwrap()
);
}
assert_eq!(compare_object, serialized.deref());
}
}
#[test]
fn unknown_content() {
assert_eq!(
Error::UnknownContentTypeMatchFromStr("Foobar".into()),
ContentType::try_from("Foobar").unwrap_err()
);
}
#[test]
#[cfg(feature = "serde-bson")]
fn test_from_str() {
assert_eq!(ContentType::Bson, "Bson".try_into().unwrap());
}
#[test]
#[cfg(feature = "serde-bson")]
fn test_from_ref_string() {
assert_eq!(ContentType::Bson, (&"Bson".to_string()).try_into().unwrap());
}
#[test]
fn test_from_ref_self() {
#[cfg(feature = "serde-bson")]
assert_eq!(
ContentType::Bson,
ContentType::try_from(&ContentType::Bson).unwrap()
);
#[cfg(feature = "serde-cbor")]
assert_eq!(
ContentType::Cbor,
ContentType::try_from(&ContentType::Cbor).unwrap()
);
#[cfg(feature = "serde-flexbuffers")]
assert_eq!(
ContentType::FlexBuffers,
ContentType::try_from(&ContentType::FlexBuffers).unwrap()
);
#[cfg(feature = "serde-json")]
assert_eq!(
ContentType::Json,
ContentType::try_from(&ContentType::Json).unwrap()
);
#[cfg(feature = "serde-json5")]
assert_eq!(
ContentType::Json5,
ContentType::try_from(&ContentType::Json5).unwrap()
);
#[cfg(feature = "serde-lexpr")]
assert_eq!(
ContentType::Lexpr,
ContentType::try_from(&ContentType::Lexpr).unwrap()
);
#[cfg(feature = "serde-messagepack")]
assert_eq!(
ContentType::MessagePack,
ContentType::try_from(&ContentType::MessagePack).unwrap()
);
#[cfg(feature = "serde-postcard")]
assert_eq!(
ContentType::Postcard,
ContentType::try_from(&ContentType::Postcard).unwrap()
);
#[cfg(feature = "serde-ron")]
assert_eq!(
ContentType::Ron,
ContentType::try_from(&ContentType::Ron).unwrap()
);
#[cfg(feature = "serde-toml")]
assert_eq!(
ContentType::Toml,
ContentType::try_from(&ContentType::Toml).unwrap()
);
#[cfg(feature = "serde-query-string")]
assert_eq!(
ContentType::QueryString,
ContentType::try_from(&ContentType::QueryString).unwrap()
);
#[cfg(feature = "serde-pickle")]
assert_eq!(
ContentType::Yaml,
ContentType::try_from(&ContentType::Yaml).unwrap()
);
#[cfg(feature = "serde-pickle")]
assert_eq!(
ContentType::Pickle,
ContentType::try_from(&ContentType::Pickle).unwrap()
);
#[cfg(feature = "serde-accept-limited-xml-serialize")]
assert_eq!(
ContentType::Xml,
ContentType::try_from(&ContentType::Xml).unwrap()
);
}
#[test]
#[cfg(feature = "serde-json")]
fn test_simple_serialization() {
let my_struct = MyStruct::default();
assert_eq!(
EXAMPLE_JSON_SERIALIZE.as_bytes(),
my_struct.encode("json").unwrap().deref()
);
assert_eq!(
EXAMPLE_JSON_SERIALIZE.as_bytes(),
my_struct.encode("application/json").unwrap().deref()
);
}
#[test]
#[cfg(feature = "serde-json")]
fn test_simple_deserialization() {
let my_struct: Decoded<MyStruct> =
EXAMPLE_JSON_DESERIALIZE.as_bytes().decode("json").unwrap();
assert_eq!(my_struct.into(), MyStruct::default());
}
#[test]
#[cfg(feature = "serde-yaml")]
fn test_yaml() {
deserialize_test("yaml", EXAMPLE_YAML_DESERIALIZE.as_bytes());
serialize_test("yaml", EXAMPLE_YAML_SERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "serde-json5")]
fn test_json5() {
deserialize_test("json5", EXAMPLE_JSON5_DESERIALIZE.as_bytes());
serialize_test("json5", EXAMPLE_JSON5_SERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "serde-json")]
fn test_json() {
deserialize_test("json", EXAMPLE_JSON_DESERIALIZE.as_bytes());
serialize_test("json", EXAMPLE_JSON_SERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "accept-limited-xml-serialize")]
fn test_xml() {
serialize_test("xml", XML_SERIALIZE.as_bytes());
deserialize_test("xml", XML_DESERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "serde-cbor")]
fn test_cbor() {
serialize_test("cbor", CBOR_SERIALIZE);
deserialize_test("cbor", CBOR_SERIALIZE);
}
#[test]
#[cfg(feature = "serde-bson")]
fn test_bson() {
serialize_test("bson", BSON_SERIALIZE);
deserialize_test("bson", BSON_SERIALIZE);
}
#[test]
#[cfg(feature = "serde-ron")]
fn test_ron() {
serialize_test("ron", RON_SERIALIZE.as_bytes());
deserialize_test("ron", RON_DESERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "serde-toml")]
fn test_toml() {
serialize_test("toml", TOML_SERIALIZE.as_bytes());
deserialize_test("toml", TOML_SERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "serde-flexbuffers")]
fn test_flex_buffers() {
serialize_test("flexbuffers", FLEXBUFFERS_SERIALIZE);
deserialize_test("flexbuffers", FLEXBUFFERS_SERIALIZE);
}
#[test]
#[cfg(feature = "serde-lexpr")]
fn test_lexpr() {
serialize_test("lexpr", LEXPR_SERIALIZE.as_bytes());
deserialize_test("lexpr", LEXPR_DESERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "serde-messagepack")]
fn test_messagepack() {
serialize_test("messagepack", MESSAGEPACK_SERIALIZE);
deserialize_test("messagepack", MESSAGEPACK_SERIALIZE);
}
#[test]
#[cfg(feature = "serde-pickle")]
fn test_pickle() {
serialize_test("pickle", PICKLE_SERIALIZE);
deserialize_test("pickle", PICKLE_SERIALIZE);
}
#[test]
#[cfg(feature = "serde-postcard")]
fn test_postcard() {
serialize_test("postcard", POSTCARD_SERIALIZE);
deserialize_test("postcard", POSTCARD_SERIALIZE);
}
#[test]
#[cfg(feature = "serde-query-string")]
fn test_url() {
serialize_test("querystring", URL_SERIALIZE.as_bytes());
deserialize_test("querystring", URL_SERIALIZE.as_bytes());
}
#[test]
#[cfg(feature = "serde-bson")]
fn test_error_from_bson_error() {
let err = Error::from(bson::ser::Error::UnsignedIntegerExceededRange(0));
assert!(matches!(err, Error::BsonSerializationFailure(_)));
let err = Error::from(bson::de::Error::EndOfStream);
assert!(matches!(err, Error::BsonDeserializationFailure(_)));
}
#[test]
fn test_documentation_example() {
#[derive(Serialize)]
struct Foo {
bar: String,
}
let my_foo = Foo {
bar: "foobar".to_string(),
};
let encoded: Encoded = my_foo
.encode("yaml")
.expect("Should have been encoded in yaml");
assert_eq!(
&vec![98, 97, 114, 58, 32, 102, 111, 111, 98, 97, 114, 10],
encoded.deref()
);
assert_eq!(
r#"bar: foobar
"#,
encoded.try_to_string().unwrap()
)
}
}