use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, ts_rs::TS, Clone, Debug, PartialEq, Eq)]
pub struct Payload {
content_type: ContentType,
bytes: Vec<u8>,
}
impl Payload {
#[must_use]
pub fn new(content_type: ContentType, bytes: Vec<u8>) -> Self {
Self {
content_type,
bytes,
}
}
pub fn from_json(value: &serde_json::Value) -> Result<Self, PayloadError> {
let bytes = serde_json::to_vec(value)?;
Ok(Self::new(ContentType::Json, bytes))
}
pub fn to_json(&self) -> Result<serde_json::Value, PayloadError> {
match self.content_type {
ContentType::Json => Ok(serde_json::from_slice(&self.bytes)?),
}
}
#[must_use]
pub const fn content_type(&self) -> &ContentType {
&self.content_type
}
#[must_use]
pub fn bytes(&self) -> &[u8] {
&self.bytes
}
}
#[derive(Serialize, Deserialize, ts_rs::TS, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ContentType {
Json,
}
#[derive(thiserror::Error, Debug)]
pub enum PayloadError {
#[error("json payload conversion failed: {0}")]
Json(#[from] serde_json::Error),
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::{ContentType, Payload};
#[test]
fn json_values_round_trip_losslessly() -> Result<(), Box<dyn std::error::Error>> {
let values = [
serde_json::Value::Null,
json!(true),
json!(123.45),
json!("hello"),
json!([null, false, 7, "item"]),
json!({"nested": {"value": 1}, "array": [true, false]}),
];
for value in values {
let payload = Payload::from_json(&value)?;
assert_eq!(payload.content_type(), &ContentType::Json);
assert_eq!(payload.to_json()?, value);
}
Ok(())
}
}