Playing with macros. Generated Attributes struct, attributes names vector and Default trait impl with a macro_rules
Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
parent
e49453f4a6
commit
27238b3f2f
|
@ -6,11 +6,11 @@ Work in progress SDK for [CloudEvents](https://github.com/cloudevents/spec)
|
|||
|
||||
| | [v0.3](https://github.com/cloudevents/spec/tree/v0.3) | [v1.0](https://github.com/cloudevents/spec/tree/v1.0) |
|
||||
| :---------------------------: | :----------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: |
|
||||
| CloudEvents Core | :x: | :heavy_check_mark: |
|
||||
| CloudEvents Core | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| AMQP Protocol Binding | :x: | :x: |
|
||||
| AVRO Event Format | :x: | :x: |
|
||||
| HTTP Protocol Binding | :x: | :x: |
|
||||
| JSON Event Format | :x: | :heavy_check_mark: |
|
||||
| JSON Event Format | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Kafka Protocol Binding | :x: | :x: |
|
||||
| MQTT Protocol Binding | :x: | :x: |
|
||||
| NATS Protocol Binding | :x: | :x: |
|
||||
|
|
|
@ -1,6 +1,79 @@
|
|||
use super::{AttributesV03, AttributesV10, SpecVersion};
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
macro_rules! attributes_def {
|
||||
// struct attributes expansion
|
||||
(@struct_gen $struct_name:ident {$(,)*} -> { $($out:tt)* }) => {
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct $struct_name {
|
||||
$($out)*
|
||||
}
|
||||
};
|
||||
(@struct_gen $struct_name:ident {$element_name:ident $(as $_element_lit:literal)?: $element_ty:ty $({$($opts:tt)*})?, $($tail:tt)*} -> {}) => {
|
||||
attributes_def!(@struct_gen $struct_name { $($tail)* } -> {pub(crate) $element_name: $element_ty});
|
||||
};
|
||||
(@struct_gen $struct_name:ident {$element_name:ident $(as $_element_lit:literal)?: $element_ty:ty $({$($opts:tt)*})?, $($tail:tt)*} -> {$($out:tt)*}) => {
|
||||
attributes_def!(@struct_gen $struct_name { $($tail)* } -> {$($out)*, pub(crate) $element_name: $element_ty});
|
||||
};
|
||||
|
||||
// count attributes
|
||||
(@count_attrs ) => {0usize};
|
||||
(@count_attrs $_element_name:ident $(as $_element_lit:literal)?: $element_ty:ty $({$($opts:tt)*})?, $($tail:tt)*) => {1usize + attributes_def!{@count_attrs $($tail)* }};
|
||||
|
||||
// names expansion
|
||||
(@attributes_gen {} -> {$($out:expr)*} ) => {
|
||||
[$($out),*]
|
||||
};
|
||||
(@attributes_gen { $element_name:ident: $_element_ty:ty $({$($_opts:tt)*})?, $($tail:tt)* } -> {$($out:tt)*}) => {
|
||||
attributes_def!(@attributes_gen {$($tail)*} -> {$($out)* stringify!($element_name)})
|
||||
};
|
||||
(@attributes_gen { $_element_name:ident as $element_lit:literal: $_element_ty:ty $({$($_opts:tt)*})? , $($tail:tt)* } -> {$($out:tt)*}) => {
|
||||
attributes_def!(@attributes_gen {$($tail)*} -> {$($out)* $element_lit})
|
||||
};
|
||||
|
||||
// attribute names expansion
|
||||
(@attribute_names_gen $attr_vec_name:ident { $($attrs:tt)* }) => {
|
||||
pub const $attr_vec_name: [&'static str; attributes_def!(@count_attrs $($attrs)*)] = attributes_def!(@attributes_gen { $($attrs)* } -> {});
|
||||
};
|
||||
|
||||
// default trait implementation expansion
|
||||
(@default_gen $struct_name:ident {$(,)*} -> { $($out:tt)* }) => {
|
||||
impl Default for $struct_name {
|
||||
fn default() -> Self {
|
||||
$struct_name {
|
||||
$($out)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
(@default_gen $struct_name:ident {
|
||||
$element_name:ident $(as $_element_lit:literal)?: $_element_ty:ty, $($tail:tt)*
|
||||
} -> { $($out:tt)* } ) => {
|
||||
attributes_def!(@default_gen $struct_name { $($tail)* } -> {$($out)* $element_name: attributes_def!(@default_gen_walk_opts {}), });
|
||||
};
|
||||
(@default_gen $struct_name:ident {
|
||||
$element_name:ident $(as $_element_lit:literal)?: $_element_ty:ty {$($opts:tt)*}, $($tail:tt)*
|
||||
} -> { $($out:tt)* } ) => {
|
||||
attributes_def!(@default_gen $struct_name { $($tail)* } -> {$($out)* $element_name: attributes_def!(@default_gen_walk_opts {$($opts)*}), });
|
||||
};
|
||||
(@default_gen_walk_opts {default: $default_expr:expr, $($tail:tt)*}) => {
|
||||
$default_expr
|
||||
};
|
||||
(@default_gen_walk_opts {$_opt_key:ident: $_opt_val:ident, $($tail:tt)*}) => {
|
||||
attributes_def!(@default_gen_walk_opts {$($tail)*})
|
||||
};
|
||||
(@default_gen_walk_opts {}) => {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
// Real macro input
|
||||
($struct_name:ident, $attr_names:ident, { $($tt:tt)* }) => {
|
||||
attributes_def!(@attribute_names_gen $attr_names { $($tt)* });
|
||||
attributes_def!(@struct_gen $struct_name { $($tt)* } -> {});
|
||||
attributes_def!(@default_gen $struct_name { $($tt)* } -> {});
|
||||
};
|
||||
}
|
||||
|
||||
/// Trait to get [CloudEvents Context attributes](https://github.com/cloudevents/spec/blob/master/spec.md#context-attributes).
|
||||
pub trait AttributesReader {
|
||||
/// Get the [id](https://github.com/cloudevents/spec/blob/master/spec.md#id).
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#[macro_use]
|
||||
mod attributes;
|
||||
mod builder;
|
||||
mod data;
|
||||
|
|
|
@ -5,16 +5,25 @@ use chrono::{DateTime, Utc};
|
|||
use hostname::get_hostname;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct Attributes {
|
||||
pub(crate) id: String,
|
||||
pub(crate) ty: String,
|
||||
pub(crate) source: String,
|
||||
pub(crate) datacontenttype: Option<String>,
|
||||
pub(crate) schemaurl: Option<String>,
|
||||
pub(crate) subject: Option<String>,
|
||||
pub(crate) time: Option<DateTime<Utc>>,
|
||||
}
|
||||
attributes_def!(
|
||||
Attributes,
|
||||
ATTRIBUTES_NAMES,
|
||||
{
|
||||
id: String {
|
||||
default: Uuid::new_v4().to_string(),
|
||||
},
|
||||
ty as "type": String {
|
||||
default: "rust.generated".to_string(),
|
||||
},
|
||||
source: String {
|
||||
default: get_hostname().unwrap_or("http://localhost/".to_string()),
|
||||
},
|
||||
datacontenttype: Option<String>,
|
||||
schemaurl: Option<String>,
|
||||
subject: Option<String>,
|
||||
time: Option<DateTime<Utc>>,
|
||||
}
|
||||
);
|
||||
|
||||
impl AttributesReader for Attributes {
|
||||
fn get_id(&self) -> &str {
|
||||
|
@ -91,20 +100,6 @@ impl DataAttributesWriter for Attributes {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for Attributes {
|
||||
fn default() -> Self {
|
||||
Attributes {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
ty: "type".to_string(),
|
||||
source: get_hostname().unwrap_or("http://localhost/".to_string()),
|
||||
datacontenttype: None,
|
||||
schemaurl: None,
|
||||
subject: None,
|
||||
time: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AttributesConverter for Attributes {
|
||||
fn into_v03(self) -> Self {
|
||||
self
|
||||
|
|
|
@ -4,16 +4,25 @@ use chrono::{DateTime, Utc};
|
|||
use hostname::get_hostname;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct Attributes {
|
||||
pub(crate) id: String,
|
||||
pub(crate) ty: String,
|
||||
pub(crate) source: String,
|
||||
pub(crate) datacontenttype: Option<String>,
|
||||
pub(crate) dataschema: Option<String>,
|
||||
pub(crate) subject: Option<String>,
|
||||
pub(crate) time: Option<DateTime<Utc>>,
|
||||
}
|
||||
attributes_def!(
|
||||
Attributes,
|
||||
ATTRIBUTES_NAMES,
|
||||
{
|
||||
id: String {
|
||||
default: Uuid::new_v4().to_string(),
|
||||
},
|
||||
ty as "type": String {
|
||||
default: "rust.generated".to_string(),
|
||||
},
|
||||
source: String {
|
||||
default: get_hostname().unwrap_or("http://localhost/".to_string()),
|
||||
},
|
||||
datacontenttype: Option<String>,
|
||||
dataschema: Option<String>,
|
||||
subject: Option<String>,
|
||||
time: Option<DateTime<Utc>>,
|
||||
}
|
||||
);
|
||||
|
||||
impl AttributesReader for Attributes {
|
||||
fn get_id(&self) -> &str {
|
||||
|
@ -33,24 +42,15 @@ impl AttributesReader for Attributes {
|
|||
}
|
||||
|
||||
fn get_datacontenttype(&self) -> Option<&str> {
|
||||
match self.datacontenttype.as_ref() {
|
||||
Some(s) => Some(&s),
|
||||
None => None,
|
||||
}
|
||||
self.datacontenttype.as_deref()
|
||||
}
|
||||
|
||||
fn get_dataschema(&self) -> Option<&str> {
|
||||
match self.dataschema.as_ref() {
|
||||
Some(s) => Some(&s),
|
||||
None => None,
|
||||
}
|
||||
self.dataschema.as_deref()
|
||||
}
|
||||
|
||||
fn get_subject(&self) -> Option<&str> {
|
||||
match self.subject.as_ref() {
|
||||
Some(s) => Some(&s),
|
||||
None => None,
|
||||
}
|
||||
self.subject.as_deref()
|
||||
}
|
||||
|
||||
fn get_time(&self) -> Option<&DateTime<Utc>> {
|
||||
|
@ -90,20 +90,6 @@ impl DataAttributesWriter for Attributes {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for Attributes {
|
||||
fn default() -> Self {
|
||||
Attributes {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
ty: "type".to_string(),
|
||||
source: get_hostname().unwrap_or("http://localhost/".to_string()),
|
||||
datacontenttype: None,
|
||||
dataschema: None,
|
||||
subject: None,
|
||||
time: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AttributesConverter for Attributes {
|
||||
fn into_v10(self) -> Self {
|
||||
self
|
||||
|
|
Loading…
Reference in New Issue