timesource-derive 0.1.3

Macros for Timesource crate
Documentation
#[macro_use]
extern crate test_case;

#[macro_use]
extern crate timesource_derive;

use minicbor::{Decode, Encode};
use serde::{Deserialize, Serialize};
use timesource::*;
use timesource_core as timesource;

#[derive(Serialize, Deserialize, TimesourceEvent, PartialEq, Debug)]
struct WithTuple(String);

#[derive(Serialize, Deserialize, TimesourceEvent, PartialEq, Debug)]
struct WithFields {
    #[allow(dead_code)]
    qty: usize,
}

#[derive(Serialize, Deserialize, TimesourceEvent, PartialEq, Debug)]
#[timesource(encoding = "json")]
enum TdbEventJson {
    Created,
    Abandoned(String),
    #[allow(dead_code)]
    AddedItem {
        id: usize,
    },
}

#[derive(Encode, Decode, TimesourceEvent, PartialEq, Debug)]
#[timesource(encoding = "cbor")]
enum TdbEventCbor {
    #[b(0)]
    Created,
    #[b(1)]
    Abandoned(#[b(0)] String),
    #[b(2)]
    AddedItem {
        #[b(0)]
        id: usize,
    },
}

mod proto {
    use super::*;
    use prost::Message;

    #[derive(Clone, PartialEq, Message)]
    pub struct Created {}
    #[derive(Clone, PartialEq, Message)]
    pub struct Abandoned {
        #[prost(string, tag = "1")]
        pub reason: ::prost::alloc::string::String,
    }
    #[derive(Clone, PartialEq, Message)]
    pub struct AddedItem {
        #[prost(uint32, tag = "1")]
        pub id: u32,
    }
    #[derive(Clone, PartialEq, Message, TimesourceEvent)]
    #[timesource(encoding = "proto")]
    pub struct TdbEvent {
        #[prost(oneof = "tdb_event_proto::Data", tags = "1, 2, 3")]
        pub data: ::core::option::Option<tdb_event_proto::Data>,
    }

    pub mod tdb_event_proto {
        #[derive(Clone, PartialEq, ::prost::Oneof)]
        pub enum Data {
            #[prost(message, tag = "1")]
            Created(super::Created),
            #[prost(message, tag = "2")]
            Abandoned(super::Abandoned),
            #[prost(message, tag = "3")]
            AddedItem(super::AddedItem),
        }
    }
}

#[test]
fn should_return_event_name() {
    assert_eq!(TdbEventJson::name(), "TdbEventJson");
    assert_eq!(WithFields::name(), "WithFields");
    assert_eq!(WithTuple::name(), "WithTuple");
}

#[test]
fn should_return_default_meta() {
    assert_eq!(WithFields::version(), None);
    assert_eq!(&format!("{:#?}", WithFields::encoding()), "Json");
}

#[test]
fn should_return_attr_meta() {
    assert_eq!(&format!("{:#?}", TdbEventJson::encoding()), "Json");
}

#[test]
fn should_encode_struct_tuple() {
    let event = WithTuple("hello".into());
    let encoded = event.encode_to_payload().unwrap();
    match encoded {
        EventPayloadEncoding::Json(value) => {
            let decoded = WithTuple::decode_from_payload(Some(&value), None).unwrap();
            assert_eq!(decoded, event);
        }
        _ => {
            unreachable!();
        }
    }
}

#[test_case(TdbEventJson::Created; "Created")]
#[test_case(TdbEventJson::Abandoned("Some reason or another".into()); "Abandoned")]
#[test_case(TdbEventJson::AddedItem { id: 1 }; "AddedItem")]
fn should_encode_json_struct_with_fields(event: TdbEventJson) {
    let encoded = event.encode_to_payload().unwrap();
    match encoded {
        EventPayloadEncoding::Json(value) => {
            let decoded = TdbEventJson::decode_from_payload(Some(&value), None).unwrap();
            assert_eq!(decoded, event);
        }
        _ => unreachable!(),
    }
}

#[test_case(TdbEventCbor::Created; "Created")]
#[test_case(TdbEventCbor::Abandoned("Some reason or another".into()); "Abandoned")]
#[test_case(TdbEventCbor::AddedItem { id: 1 }; "AddedItem")]
fn should_encode_cbor_struct_with_fields(event: TdbEventCbor) {
    let encoded = event.encode_to_payload().unwrap();
    match encoded {
        EventPayloadEncoding::Bytes(bytes) => {
            let decoded = TdbEventCbor::decode_from_payload(None, Some(&bytes)).unwrap();
            assert_eq!(decoded, event);
        }
        _ => unreachable!(),
    }
}

#[test_case(proto::TdbEvent { data: Some(proto::tdb_event_proto::Data::Created(proto::Created {})) }; "Created")]
#[test_case(proto::TdbEvent { data: Some(proto::tdb_event_proto::Data::Abandoned(proto::Abandoned { reason : "Some reason or another".into() })) }; "Abandoned")]
#[test_case(proto::TdbEvent { data: Some(proto::tdb_event_proto::Data::AddedItem(proto::AddedItem { id: 1 })) }; "AddedItem")]
fn should_encode_proto_struct_with_fields(event: proto::TdbEvent) {
    let encoded = event.encode_to_payload().unwrap();
    match encoded {
        EventPayloadEncoding::Bytes(bytes) => {
            let decoded = proto::TdbEvent::decode_from_payload(None, Some(&bytes)).unwrap();
            assert_eq!(decoded, event);
        }
        _ => unreachable!(),
    }
}

#[test]
fn should_encode_enum() {
    let event = WithFields { qty: 1 };
    let encoded = event.encode_to_payload().unwrap();
    match encoded {
        EventPayloadEncoding::Json(value) => {
            let decoded = WithFields::decode_from_payload(Some(&value), None).unwrap();
            assert_eq!(decoded, event);
        }
        _ => {
            unreachable!();
        }
    }
}