use super::custom_serde::*;
use chrono::{DateTime, Duration, Utc};
use std::borrow::Cow;
use std::ops::{Deref, DerefMut};
use base64::display::Base64Display;
use serde::de::{Deserialize, Deserializer, Error as DeError, Visitor};
use serde::ser::{Error as SerError, Serialize, Serializer};
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct Base64Data(
#[serde(deserialize_with = "deserialize_base64")]
#[serde(serialize_with = "serialize_base64")]
pub Vec<u8>,
);
impl Deref for Base64Data {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Base64Data {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct MillisecondTimestamp(
#[serde(deserialize_with = "deserialize_milliseconds")]
#[serde(serialize_with = "serialize_milliseconds")]
pub DateTime<Utc>,
);
impl Deref for MillisecondTimestamp {
type Target = DateTime<Utc>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for MillisecondTimestamp {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct SecondTimestamp(
#[serde(deserialize_with = "deserialize_seconds")]
#[serde(serialize_with = "serialize_seconds")]
pub DateTime<Utc>,
);
impl Deref for SecondTimestamp {
type Target = DateTime<Utc>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SecondTimestamp {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct SecondDuration(
#[serde(deserialize_with = "deserialize_duration_seconds")]
#[serde(serialize_with = "serialize_duration_seconds")]
pub Duration,
);
impl Deref for SecondDuration {
type Target = Duration;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SecondDuration {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct MinuteDuration(
#[serde(deserialize_with = "deserialize_duration_minutes")]
#[serde(serialize_with = "serialize_duration_minutes")]
pub Duration,
);
impl Deref for MinuteDuration {
type Target = Duration;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for MinuteDuration {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug, PartialEq)]
pub enum Body {
Empty,
Text(String),
Binary(Vec<u8>),
}
impl Body {
pub fn from_maybe_encoded(is_base64_encoded: bool, body: &str) -> Body {
if is_base64_encoded {
Body::from(::base64::decode(body).expect("failed to decode aws base64 encoded body"))
} else {
Body::from(body)
}
}
}
impl Default for Body {
fn default() -> Self {
Body::Empty
}
}
impl From<()> for Body {
fn from(_: ()) -> Self {
Body::Empty
}
}
impl<'a> From<&'a str> for Body {
fn from(s: &'a str) -> Self {
Body::Text(s.into())
}
}
impl From<String> for Body {
fn from(b: String) -> Self {
Body::Text(b)
}
}
impl From<Cow<'static, str>> for Body {
#[inline]
fn from(cow: Cow<'static, str>) -> Body {
match cow {
Cow::Borrowed(b) => Body::from(b.to_owned()),
Cow::Owned(o) => Body::from(o),
}
}
}
impl From<Cow<'static, [u8]>> for Body {
#[inline]
fn from(cow: Cow<'static, [u8]>) -> Body {
match cow {
Cow::Borrowed(b) => Body::from(b),
Cow::Owned(o) => Body::from(o),
}
}
}
impl From<Vec<u8>> for Body {
fn from(b: Vec<u8>) -> Self {
Body::Binary(b)
}
}
impl<'a> From<&'a [u8]> for Body {
fn from(b: &'a [u8]) -> Self {
Body::Binary(b.to_vec())
}
}
impl Deref for Body {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl AsRef<[u8]> for Body {
#[inline]
fn as_ref(&self) -> &[u8] {
match self {
Body::Empty => &[],
Body::Text(ref bytes) => bytes.as_ref(),
Body::Binary(ref bytes) => bytes.as_ref(),
}
}
}
impl Clone for Body {
fn clone(&self) -> Self {
match self {
Body::Empty => Body::Empty,
Body::Text(ref bytes) => Body::Text(bytes.clone()),
Body::Binary(ref bytes) => Body::Binary(bytes.clone()),
}
}
}
impl<'a> Serialize for Body {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Body::Text(data) => serializer
.serialize_str(::std::str::from_utf8(data.as_ref()).map_err(S::Error::custom)?),
Body::Binary(data) => {
serializer.collect_str(&Base64Display::with_config(data, base64::STANDARD))
}
Body::Empty => serializer.serialize_unit(),
}
}
}
impl<'de> Deserialize<'de> for Body {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct BodyVisitor;
impl<'de> Visitor<'de> for BodyVisitor {
type Value = Body;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("string")
}
fn visit_str<E>(self, value: &str) -> Result<Body, E>
where
E: DeError,
{
Ok(Body::from(value))
}
}
deserializer.deserialize_str(BodyVisitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json;
use std::collections::HashMap;
#[test]
fn body_has_default() {
assert_eq!(Body::default(), Body::Empty);
}
#[test]
fn from_unit() {
assert_eq!(Body::from(()), Body::Empty);
}
#[test]
fn from_str() {
match Body::from(String::from("foo").as_str()) {
Body::Text(_) => (),
not => assert!(false, "expected Body::Text(...) got {:?}", not),
}
}
#[test]
fn from_string() {
match Body::from(String::from("foo")) {
Body::Text(_) => (),
not => assert!(false, "expected Body::Text(...) got {:?}", not),
}
}
#[test]
fn from_cow_str() {
match Body::from(Cow::from("foo")) {
Body::Text(_) => (),
not => assert!(false, "expected Body::Text(...) got {:?}", not),
}
}
#[test]
fn from_cow_bytes() {
match Body::from(Cow::from("foo".as_bytes())) {
Body::Binary(_) => (),
not => assert!(false, "expected Body::Binary(...) got {:?}", not),
}
}
#[test]
fn from_bytes() {
match Body::from("foo".as_bytes()) {
Body::Binary(_) => (),
not => assert!(false, "expected Body::Binary(...) got {:?}", not),
}
}
#[test]
fn serialize_text() {
let mut map = HashMap::new();
map.insert("foo", Body::from("bar"));
assert_eq!(serde_json::to_string(&map).unwrap(), r#"{"foo":"bar"}"#);
}
#[test]
fn serialize_binary() {
let mut map = HashMap::new();
map.insert("foo", Body::from("bar".as_bytes()));
assert_eq!(serde_json::to_string(&map).unwrap(), r#"{"foo":"YmFy"}"#);
}
#[test]
fn serialize_empty() {
let mut map = HashMap::new();
map.insert("foo", Body::Empty);
assert_eq!(serde_json::to_string(&map).unwrap(), r#"{"foo":null}"#);
}
#[test]
fn serialize_from_maybe_encoded() {
match Body::from_maybe_encoded(false, "foo") {
Body::Text(_) => (),
not => assert!(false, "expected Body::Text(...) got {:?}", not),
}
match Body::from_maybe_encoded(true, "Zm9v") {
Body::Binary(b) => assert_eq!(&[102, 111, 111], b.as_slice()),
not => assert!(false, "expected Body::Text(...) got {:?}", not),
}
}
}