use crate::prelude::*;
use serde::ser::SerializeMap;
use serde::{de, ser};
use std::fmt;
#[derive(Default, Serialize, Deserialize)]
pub struct RecordReplayRecords {
pub requests: Vec<RecordReplayRecord>,
}
#[derive(Serialize, Deserialize)]
pub struct RecordReplayRecord {
#[serde(
serialize_with = "serialize_method",
deserialize_with = "deserialize_method"
)]
pub method: Method,
#[serde(serialize_with = "serialize_uri", deserialize_with = "deserialize_uri")]
pub uri: Uri,
#[serde(
serialize_with = "serialize_header_map",
deserialize_with = "deserialize_header_map",
skip_serializing_if = "Option::is_none",
default
)]
pub headers: Option<HeaderMap<HeaderValue>>,
#[serde(
serialize_with = "serialize_option_bytes",
deserialize_with = "deserialize_option_bytes",
skip_serializing_if = "Option::is_none",
default
)]
pub body: Option<Bytes>,
pub response: RecordReplayRecordResponse,
}
#[derive(Serialize, Deserialize)]
pub struct RecordReplayRecordResponse {
#[serde(
serialize_with = "serialize_status_code",
deserialize_with = "deserialize_status_code"
)]
pub status: StatusCode,
#[serde(
serialize_with = "serialize_header_map",
deserialize_with = "deserialize_header_map",
skip_serializing_if = "Option::is_none",
default
)]
pub headers: Option<HeaderMap<HeaderValue>>,
#[serde(
serialize_with = "serialize_bytes",
deserialize_with = "deserialize_bytes"
)]
pub body: Bytes,
}
fn serialize_method<S>(method: &Method, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(method.as_str())
}
fn deserialize_method<'de, D>(deserializer: D) -> Result<Method, D::Error>
where
D: de::Deserializer<'de>,
{
struct MethodVisitor;
impl<'de> de::Visitor<'de> for MethodVisitor {
type Value = Method;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a valid HTTP method")
}
fn visit_str<E>(self, v: &str) -> Result<Method, E>
where
E: de::Error,
{
Method::from_bytes(v.as_bytes()).map_err(E::custom)
}
}
deserializer.deserialize_str(MethodVisitor)
}
fn serialize_uri<S>(uri: &Uri, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(uri.to_string().as_str())
}
fn deserialize_uri<'de, D>(deserializer: D) -> Result<Uri, D::Error>
where
D: de::Deserializer<'de>,
{
struct UriVisitor;
impl<'de> de::Visitor<'de> for UriVisitor {
type Value = Uri;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a valid HTTP URI")
}
fn visit_str<E>(self, v: &str) -> Result<Uri, E>
where
E: de::Error,
{
v.parse::<Uri>().map_err(E::custom)
}
}
deserializer.deserialize_str(UriVisitor)
}
fn serialize_status_code<S>(code: &StatusCode, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_i64(code.as_u16() as i64)
}
fn deserialize_status_code<'de, D>(deserializer: D) -> Result<StatusCode, D::Error>
where
D: de::Deserializer<'de>,
{
struct StatusCodeVisitor;
impl<'de> de::Visitor<'de> for StatusCodeVisitor {
type Value = StatusCode;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a valid HTTP status code")
}
fn visit_i64<E>(self, v: i64) -> Result<StatusCode, E>
where
E: de::Error,
{
StatusCode::from_u16(v as u16).map_err(E::custom)
}
fn visit_u64<E>(self, v: u64) -> Result<StatusCode, E>
where
E: de::Error,
{
self.visit_i64(v as i64)
}
}
deserializer.deserialize_i64(StatusCodeVisitor)
}
fn serialize_header_map<S>(
headers: &Option<HeaderMap<HeaderValue>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match headers {
Some(headers) => {
let mut map = HashMap::new();
for (key, value) in headers.iter() {
map.insert(
key.as_str().to_owned(),
value.to_str().unwrap_or("").to_owned(),
);
}
serializer.serialize_map(Some(map.len()))?.end()
}
None => serializer.serialize_none(),
}
}
fn deserialize_header_map<'de, D>(
deserializer: D,
) -> Result<Option<HeaderMap<HeaderValue>>, D::Error>
where
D: de::Deserializer<'de>,
{
struct HeaderMapVisitor;
impl<'de> de::Visitor<'de> for HeaderMapVisitor {
type Value = Option<HeaderMap<HeaderValue>>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a header map")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Option<HeaderMap<HeaderValue>>, V::Error>
where
V: de::MapAccess<'de>,
{
let mut map = HeaderMap::new();
while let Some((key, value)) = visitor.next_entry::<String, String>()? {
map.insert(key.parse::<HeaderName>().unwrap(), value.parse().unwrap());
}
Ok(Some(map))
}
}
deserializer.deserialize_map(HeaderMapVisitor)
}
fn serialize_bytes<S>(bytes: &Bytes, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
let string = String::from_utf8(bytes.to_vec())
.map_err(|e| ser::Error::custom(format!("Invalid UTF-8: {}", e)))?;
serializer.serialize_str(&string)
}
fn deserialize_bytes<'de, D>(deserializer: D) -> Result<Bytes, D::Error>
where
D: de::Deserializer<'de>,
{
struct BytesVisitor;
impl<'de> de::Visitor<'de> for BytesVisitor {
type Value = Bytes;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a body string")
}
fn visit_str<E>(self, v: &str) -> Result<Bytes, E>
where
E: de::Error,
{
Ok(Bytes::from(v.as_bytes().to_vec()))
}
}
deserializer.deserialize_str(BytesVisitor)
}
fn serialize_option_bytes<S>(bytes: &Option<Bytes>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match bytes {
Some(bytes) => serialize_bytes(bytes, serializer),
None => serializer.serialize_none(),
}
}
fn deserialize_option_bytes<'de, D>(deserializer: D) -> Result<Option<Bytes>, D::Error>
where
D: de::Deserializer<'de>,
{
struct OptionBytesVisitor;
impl<'de> de::Visitor<'de> for OptionBytesVisitor {
type Value = Option<Bytes>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "an optional body string")
}
fn visit_none<E>(self) -> Result<Option<Bytes>, E>
where
E: de::Error,
{
Ok(None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Option<Bytes>, D::Error>
where
D: de::Deserializer<'de>,
{
let bytes = deserialize_bytes(deserializer)?;
Ok(Some(bytes))
}
}
deserializer.deserialize_option(OptionBytesVisitor)
}