timesource-derive 0.1.3

Macros for Timesource crate
Documentation
use proc_macro2::TokenStream;

pub enum PayloadEncoding {
    Json,
    Cbor,
    ProtoBuf,
}

impl TryFrom<&str> for PayloadEncoding {
    type Error = &'static str;

    fn try_from(s: &str) -> Result<Self, Self::Error> {
        match s {
        "json" => Ok(PayloadEncoding::Json),
        "cbor" => Ok(PayloadEncoding::Cbor),
        "proto" => Ok(PayloadEncoding::ProtoBuf),
        _ => Err("Unexpected payload type for timesource event. Supported: \"json\", \"bincode\" or \"prost\"")
    }
    }
}

impl quote::ToTokens for PayloadEncoding {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let token = match self {
            PayloadEncoding::Json => {
                quote! {
                    fn encode_to_payload(&self) -> Result<timesource::EventPayloadEncoding, timesource::PersistedError> {
                        let value = serde_json::to_string(self).map_err(timesource::PersistedError::from)?;
                        Ok(timesource::EventPayloadEncoding::Json(value))
                    }

                    fn decode_from_payload(json: Option<&str>, bytes: Option<&[u8]>) -> Result<Self, timesource::PersistedError> {
                        match json {
                            Some(json) => serde_json::from_str(&json).map_err(timesource::PersistedError::from),
                            None => Err(timesource::PersistedError::JsonMissing)
                        }
                    }
                }
            }
            PayloadEncoding::Cbor => {
                quote! {
                    fn encode_to_payload(&self) -> Result<timesource::EventPayloadEncoding, timesource::PersistedError> {
                        let mut buf = vec![];
                        minicbor::encode(self, &mut buf).map_err(|err| timesource::PersistedError::MiniCborEncode(format!("{}", err)))?;
                        Ok(timesource::EventPayloadEncoding::Bytes(buf))
                    }

                    fn decode_from_payload(json: Option<&str>, bytes: Option<&[u8]>) -> Result<Self, timesource::PersistedError> {
                        match bytes {
                            Some(bytes) => minicbor::decode(bytes).map_err(timesource::PersistedError::from),
                            None => Err(timesource::PersistedError::BytesMissing)
                        }
                    }
                }
            }
            PayloadEncoding::ProtoBuf => {
                quote! {
                    fn encode_to_payload(&self) -> Result<timesource::EventPayloadEncoding, timesource::PersistedError> {
                        let bytes = prost::Message::encode_to_vec(self);
                        Ok(timesource::EventPayloadEncoding::Bytes(bytes))
                    }

                    fn decode_from_payload(json: Option<&str>, bytes: Option<&[u8]>) -> Result<Self, timesource::PersistedError> {
                        match bytes {
                            Some(bytes) => Self::decode(bytes).map_err(timesource::PersistedError::from),
                            None => Err(timesource::PersistedError::BytesMissing)
                        }
                    }
                }
            }
        };

        tokens.extend(quote! {
            #token
        });
    }
}