rusoto_core 0.47.0

AWS SDK for Rust - Core
Documentation
use std::fmt::{Formatter, Result as FmtResult};

use base64;
use bytes::Bytes;
use serde::de::{Error as SerdeError, SeqAccess, Visitor};
use serde::ser::SerializeSeq;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

pub trait SerdeBlob: Sized {
    fn deserialize_blob<'de, D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>;

    fn serialize_blob<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer;
}

struct BlobVisitor;

impl<'de> Visitor<'de> for BlobVisitor {
    type Value = Bytes;

    fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
        write!(formatter, "a blob")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: SerdeError,
    {
        base64::decode(v)
            .map(Bytes::from)
            .map_err(|err| SerdeError::custom(err.to_string()))
    }
}

impl SerdeBlob for Bytes {
    fn deserialize_blob<'de, D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_any(BlobVisitor)
    }

    fn serialize_blob<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&base64::encode(self.as_ref()))
    }
}

struct OptionalBlobVisitor;

impl<'de> Visitor<'de> for OptionalBlobVisitor {
    type Value = Option<Bytes>;

    fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
        write!(formatter, "a blob")
    }

    fn visit_none<E>(self) -> Result<Self::Value, E>
    where
        E: SerdeError,
    {
        Ok(None)
    }

    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        Ok(Some(SerdeBlob::deserialize_blob(deserializer)?))
    }
}

impl SerdeBlob for Option<Bytes> {
    fn deserialize_blob<'de, D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_option(OptionalBlobVisitor)
    }

    fn serialize_blob<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            Some(ref vec) => SerdeBlob::serialize_blob(vec, serializer),
            None => serializer.serialize_none(),
        }
    }
}

struct DeserializeWrapper<T>(T);

impl<'de, T> Deserialize<'de> for DeserializeWrapper<T>
where
    T: SerdeBlob,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        Ok(DeserializeWrapper(T::deserialize_blob(deserializer)?))
    }
}

struct SerializeWrapper<'a, T>(&'a T);

impl<'a, T> Serialize for SerializeWrapper<'a, T>
where
    T: SerdeBlob,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        T::serialize_blob(self.0, serializer)
    }
}

pub trait SerdeBlobList: Sized {
    fn deserialize_blob_list<'de, D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>;

    fn serialize_blob_list<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer;
}

struct BlobListVisitor;

impl<'de> Visitor<'de> for BlobListVisitor {
    type Value = Vec<Bytes>;

    fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
        write!(formatter, "a list of blobs")
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        let mut blob_list = Vec::new();
        while let Some(DeserializeWrapper(blob)) = seq.next_element()? {
            blob_list.push(blob);
        }
        Ok(blob_list)
    }
}

impl SerdeBlobList for Vec<Bytes> {
    fn deserialize_blob_list<'de, D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_seq(BlobListVisitor)
    }

    fn serialize_blob_list<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut seq = serializer.serialize_seq(Some(self.len()))?;
        for blob in self.iter() {
            seq.serialize_element(&SerializeWrapper(blob))?;
        }
        seq.end()
    }
}

struct OptionalBlobListVisitor;

impl<'de> Visitor<'de> for OptionalBlobListVisitor {
    type Value = Option<Vec<Bytes>>;

    fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
        write!(formatter, "an optional blob list")
    }

    fn visit_none<E>(self) -> Result<Self::Value, E>
    where
        E: SerdeError,
    {
        Ok(None)
    }

    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        Ok(Some(SerdeBlobList::deserialize_blob_list(deserializer)?))
    }
}

impl SerdeBlobList for Option<Vec<Bytes>> {
    fn deserialize_blob_list<'de, D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_option(OptionalBlobListVisitor)
    }

    fn serialize_blob_list<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            Some(ref list) => SerdeBlobList::serialize_blob_list(list, serializer),
            None => serializer.serialize_none(),
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate serde;
    extern crate serde_json;

    use super::{SerdeBlob, SerdeBlobList};
    use bytes::Bytes;

    #[test]
    fn serialize_optional_blob_when_none() {
        let blob: Option<Bytes> = None;
        let serialized = serialize_blob_helper(blob);

        assert_eq!("null", serialized);
    }

    #[test]
    fn serialize_optional_blob_when_empty() {
        let blob = Some(Bytes::new());
        let serialized = serialize_blob_helper(blob);

        assert_eq!("\"\"", serialized);
    }

    #[test]
    fn serialize_optional_blob_when_has_content() {
        let blob = Some(Bytes::from_static(b"hello world!"));
        let serialized = serialize_blob_helper(blob);

        assert_eq!("\"aGVsbG8gd29ybGQh\"", serialized);
    }

    #[test]
    fn deserialize_optional_blob_when_null() {
        let deserialized: Option<Bytes> = deserialize_blob_helper("null").unwrap();

        assert!(deserialized.is_none());
    }

    #[test]
    fn deserialize_optional_blob_when_empty() {
        let deserialized: Option<Bytes> = deserialize_blob_helper("\"\"").unwrap();

        assert_eq!(Some(Bytes::new()), deserialized);
    }

    #[test]
    fn deserialize_optional_blob_when_has_content() {
        let deserialized: Option<Bytes> = deserialize_blob_helper("\"aGVsbG8gd29ybGQh\"").unwrap();

        assert_eq!(Some(Bytes::from_static(b"hello world!")), deserialized);
    }

    #[test]
    fn serialize_blob_when_empty() {
        let blob = Bytes::new();
        let serialized = serialize_blob_helper(blob);

        assert_eq!("\"\"", serialized);
    }

    #[test]
    fn serialize_blob_when_has_content() {
        let blob = Bytes::from_static(b"hello world!");
        let serialized = serialize_blob_helper(blob);

        assert_eq!("\"aGVsbG8gd29ybGQh\"", serialized);
    }

    #[test]
    fn deserialize_blob_when_null() {
        let deserialized: Result<Bytes, _> = deserialize_blob_helper("null");

        assert!(deserialized.is_err());
    }

    #[test]
    fn deserialize_blob_when_empty() {
        let deserialized: Bytes = deserialize_blob_helper("\"\"").unwrap();

        assert_eq!(Bytes::new(), deserialized);
    }

    #[test]
    fn deserialize_blob_when_has_content() {
        let deserialized: Bytes = deserialize_blob_helper("\"aGVsbG8gd29ybGQh\"").unwrap();

        assert_eq!(Bytes::from_static(b"hello world!"), deserialized);
    }

    #[test]
    fn serialize_blob_list_when_empty() {
        let blob_list = vec![];
        let serialized = serialize_blob_list_helper(blob_list);

        assert_eq!("[]", serialized);
    }

    #[test]
    fn serialize_blob_list_when_has_content() {
        let blob_list = vec![
            Bytes::from_static(b"Sunny"),
            Bytes::from_static(b"Rainy"),
            Bytes::from_static(b"Snowy"),
        ];
        let serialized = serialize_blob_list_helper(blob_list);

        assert_eq!("[\"U3Vubnk=\",\"UmFpbnk=\",\"U25vd3k=\"]", serialized);
    }

    #[test]
    fn deserialize_blob_list_when_empty() {
        let deserialized: Vec<Bytes> = deserialize_blob_list_helper("[]").unwrap();

        assert_eq!(Vec::<Bytes>::new(), deserialized);
    }

    #[test]
    fn deserialize_blob_list_when_has_content() {
        let deserialized: Vec<Bytes> =
            deserialize_blob_list_helper("[\"U3Vubnk=\",\"UmFpbnk=\",\"U25vd3k=\"]").unwrap();

        assert_eq!(
            vec![
                Bytes::from_static(b"Sunny"),
                Bytes::from_static(b"Rainy"),
                Bytes::from_static(b"Snowy")
            ],
            deserialized
        );
    }

    fn serialize_blob_helper<B: SerdeBlob>(blob: B) -> String {
        let mut serialized_data = Vec::new();
        {
            let mut json_serializer = serde_json::Serializer::new(&mut serialized_data);
            blob.serialize_blob(&mut json_serializer).unwrap();
        }
        String::from_utf8_lossy(&serialized_data).into_owned()
    }

    fn deserialize_blob_helper<B: SerdeBlob>(
        s: &str,
    ) -> Result<
        B,
        <&mut serde_json::de::Deserializer<serde_json::de::StrRead> as serde::Deserializer>::Error,
    > {
        let reader = serde_json::de::StrRead::new(s);
        let mut deserializer = serde_json::de::Deserializer::new(reader);
        B::deserialize_blob(&mut deserializer)
    }

    fn serialize_blob_list_helper<B: SerdeBlobList>(blob_list: B) -> String {
        let mut serialized_data = Vec::new();
        {
            let mut json_serializer = serde_json::Serializer::new(&mut serialized_data);
            blob_list.serialize_blob_list(&mut json_serializer).unwrap();
        }
        String::from_utf8_lossy(&serialized_data).into_owned()
    }

    fn deserialize_blob_list_helper<B: SerdeBlobList>(
        s: &str,
    ) -> Result<
        B,
        <&mut serde_json::de::Deserializer<serde_json::de::StrRead> as serde::Deserializer>::Error,
    > {
        let reader = serde_json::de::StrRead::new(s);
        let mut deserializer = serde_json::de::Deserializer::new(reader);
        B::deserialize_blob_list(&mut deserializer)
    }
}