use bytes::Bytes;
use std::convert::Infallible;
const APPLICATION_JSON: &str = "application/json";
const APPLICATION_OCTET_STREAM: &str = "application/octet-stream";
pub trait Serialize {
type Error: std::error::Error + Send + Sync + 'static;
fn serialize(&self) -> Result<Bytes, Self::Error>;
}
pub trait Deserialize
where
Self: Sized,
{
type Error: std::error::Error + Send + Sync + 'static;
fn deserialize(bytes: &mut Bytes) -> Result<Self, Self::Error>;
}
pub trait PayloadMetadata {
fn json_schema() -> Option<serde_json::Value> {
Some(serde_json::Value::Object(serde_json::Map::default()))
}
fn input_metadata() -> InputMetadata {
InputMetadata::default()
}
fn output_metadata() -> OutputMetadata {
OutputMetadata::default()
}
}
pub struct InputMetadata {
pub accept_content_type: &'static str,
pub is_required: bool,
}
impl Default for InputMetadata {
fn default() -> Self {
Self {
accept_content_type: APPLICATION_JSON,
is_required: true,
}
}
}
pub struct OutputMetadata {
pub content_type: &'static str,
pub set_content_type_if_empty: bool,
}
impl Default for OutputMetadata {
fn default() -> Self {
Self {
content_type: APPLICATION_JSON,
set_content_type_if_empty: false,
}
}
}
impl Serialize for () {
type Error = Infallible;
fn serialize(&self) -> Result<Bytes, Self::Error> {
Ok(Bytes::new())
}
}
impl Deserialize for () {
type Error = Infallible;
fn deserialize(_: &mut Bytes) -> Result<Self, Self::Error> {
Ok(())
}
}
impl Serialize for Vec<u8> {
type Error = Infallible;
fn serialize(&self) -> Result<Bytes, Self::Error> {
Ok(Bytes::copy_from_slice(self))
}
}
impl Deserialize for Vec<u8> {
type Error = Infallible;
fn deserialize(b: &mut Bytes) -> Result<Self, Self::Error> {
Ok(b.to_vec())
}
}
impl PayloadMetadata for Vec<u8> {
fn json_schema() -> Option<serde_json::Value> {
None
}
fn input_metadata() -> InputMetadata {
InputMetadata {
accept_content_type: "*/*",
is_required: true,
}
}
fn output_metadata() -> OutputMetadata {
OutputMetadata {
content_type: APPLICATION_OCTET_STREAM,
set_content_type_if_empty: false,
}
}
}
impl Serialize for Bytes {
type Error = Infallible;
fn serialize(&self) -> Result<Bytes, Self::Error> {
Ok(self.clone())
}
}
impl Deserialize for Bytes {
type Error = Infallible;
fn deserialize(b: &mut Bytes) -> Result<Self, Self::Error> {
Ok(b.clone())
}
}
impl PayloadMetadata for Bytes {
fn json_schema() -> Option<serde_json::Value> {
None
}
fn input_metadata() -> InputMetadata {
InputMetadata {
accept_content_type: "*/*",
is_required: true,
}
}
fn output_metadata() -> OutputMetadata {
OutputMetadata {
content_type: APPLICATION_OCTET_STREAM,
set_content_type_if_empty: false,
}
}
}
impl<T: Serialize> Serialize for Option<T> {
type Error = T::Error;
fn serialize(&self) -> Result<Bytes, Self::Error> {
if self.is_none() {
return Ok(Bytes::new());
}
T::serialize(self.as_ref().unwrap())
}
}
impl<T: Deserialize> Deserialize for Option<T> {
type Error = T::Error;
fn deserialize(b: &mut Bytes) -> Result<Self, Self::Error> {
if b.is_empty() {
return Ok(None);
}
T::deserialize(b).map(Some)
}
}
impl<T: PayloadMetadata> PayloadMetadata for Option<T> {
fn input_metadata() -> InputMetadata {
InputMetadata {
accept_content_type: T::input_metadata().accept_content_type,
is_required: false,
}
}
fn output_metadata() -> OutputMetadata {
OutputMetadata {
content_type: T::output_metadata().content_type,
set_content_type_if_empty: false,
}
}
}
macro_rules! impl_integer_primitives {
($ty:ty) => {
impl Serialize for $ty {
type Error = serde_json::Error;
fn serialize(&self) -> Result<Bytes, Self::Error> {
serde_json::to_vec(&self).map(Bytes::from)
}
}
impl Deserialize for $ty {
type Error = serde_json::Error;
fn deserialize(bytes: &mut Bytes) -> Result<Self, Self::Error> {
serde_json::from_slice(&bytes)
}
}
impl PayloadMetadata for $ty {
fn json_schema() -> Option<serde_json::Value> {
let min = <$ty>::MIN;
let max = <$ty>::MAX;
Some(serde_json::json!({ "type": "integer", "minimum": min, "maximum": max }))
}
}
};
}
impl_integer_primitives!(u8);
impl_integer_primitives!(u16);
impl_integer_primitives!(u32);
impl_integer_primitives!(u64);
impl_integer_primitives!(u128);
impl_integer_primitives!(i8);
impl_integer_primitives!(i16);
impl_integer_primitives!(i32);
impl_integer_primitives!(i64);
impl_integer_primitives!(i128);
macro_rules! impl_serde_primitives {
($ty:ty) => {
impl Serialize for $ty {
type Error = serde_json::Error;
fn serialize(&self) -> Result<Bytes, Self::Error> {
serde_json::to_vec(&self).map(Bytes::from)
}
}
impl Deserialize for $ty {
type Error = serde_json::Error;
fn deserialize(bytes: &mut Bytes) -> Result<Self, Self::Error> {
serde_json::from_slice(&bytes)
}
}
};
}
impl_serde_primitives!(String);
impl_serde_primitives!(bool);
impl_serde_primitives!(f32);
impl_serde_primitives!(f64);
impl PayloadMetadata for String {
fn json_schema() -> Option<serde_json::Value> {
Some(serde_json::json!({ "type": "string" }))
}
}
impl PayloadMetadata for bool {
fn json_schema() -> Option<serde_json::Value> {
Some(serde_json::json!({ "type": "boolean" }))
}
}
impl PayloadMetadata for f32 {
fn json_schema() -> Option<serde_json::Value> {
Some(serde_json::json!({ "type": "number" }))
}
}
impl PayloadMetadata for f64 {
fn json_schema() -> Option<serde_json::Value> {
Some(serde_json::json!({ "type": "number" }))
}
}
pub struct Json<T>(pub T);
impl<T> Json<T> {
pub fn into_inner(self) -> T {
self.0
}
}
impl<T> From<T> for Json<T> {
fn from(value: T) -> Self {
Self(value)
}
}
impl<T> Serialize for Json<T>
where
T: serde::Serialize,
{
type Error = serde_json::Error;
fn serialize(&self) -> Result<Bytes, Self::Error> {
serde_json::to_vec(&self.0).map(Bytes::from)
}
}
impl<T> Deserialize for Json<T>
where
for<'a> T: serde::Deserialize<'a>,
{
type Error = serde_json::Error;
fn deserialize(bytes: &mut Bytes) -> Result<Self, Self::Error> {
serde_json::from_slice(bytes).map(Json)
}
}
impl<T: Default> Default for Json<T> {
fn default() -> Self {
Self(T::default())
}
}
#[cfg(not(feature = "schemars"))]
impl<T> PayloadMetadata for Json<T> {
fn json_schema() -> Option<serde_json::Value> {
Some(serde_json::json!({}))
}
}
#[cfg(feature = "schemars")]
impl<T: schemars::JsonSchema> PayloadMetadata for Json<T> {
fn json_schema() -> Option<serde_json::Value> {
Some(schemars::schema_for!(T).to_value())
}
}