I documented the macro a bit in the charming-derive/src/lib.rs file. A well formatted version can be seen when using cargo doc. You can check what the macro expands to when using cargo expand --test derive_test in the charming-derive folder.
Current implementation
#[derive(Serialize, Debug, Clone)]
struct Chart {
#[serde(skip_serializing_if = "Vec::is_empty")]
title: Vec<Title>,
#[serde(skip_serializing_if = "Option::is_none")]
tooltip: Option<Tooltip>,
// many fields cut for brevity
}
// For setting these fields with the setter pattern we would need to implement the following
// methods manually when we are not using the derive macro
impl Chart {
pub fn new() -> Self {
Self {
title: Vec::new(),
tooltip: None,
}
}
pub fn title<T: Into<Title>>(mut self, title: T) -> Self {
self.title.push(title.into());
self
}
pub fn tooltip<T: Into<Tooltip>>(mut self, tooltip: T) -> Self {
self.tooltip = Some(tooltip.into());
self
}
// many methods cut for brevity
}
// Example chart creation
let chart = Chart::new().title(Title::new().text("Title")).tooltip(Tooltip::new());
Implementation with the macro
#[derive(Serialize, Debug, Clone, CharmingSetter)]
struct Chart {
#[serde(skip_serializing_if = "Vec::is_empty")]
title: Vec<Title>,
#[serde(skip_serializing_if = "Option::is_none")]
tooltip: Option<Tooltip>,
// many fields cut for brevity
}
// The setter methods from the example above now get implemented automatically by CharmingSetter
// Example chart creation
let chart = Chart::new().title(Title::new().text("Title")).tooltip(Tooltip::new());
I also added two field attributes charming_type and charming_skip_setter, their uses can be seen below
#[derive(Serialize, Debug, Clone, CharmingSetter)]
#[serde(rename_all = "camelCase")]
pub struct Line {
// charming_type gets used here to provide the value "line" as the default value for
// the field 'type_' when calling Line::new() and also removes the method to set the field
#[serde(rename = "type")]
#[charming_type = "line"]
type_: String,
// cut for brevity
// charming_skip_setter gets used here to remove the default implementation of the setter
// method for this field, a manual method to set this field needs to be provided instead
#[serde(skip_serializing_if = "Vec::is_empty")]
#[charming_skip_setter]
data: Vec<DataPoint>,
}
impl Line {
pub fn data<D: Into<DataPoint>>(mut self, data: Vec<D>) -> Self {
self.data = data.into_iter().map(|d| d.into()).collect();
self
}
}
This is just a draft. I will implement more tests first and then open another PR where we derive the new macro on all applicable structs. Just want to get some feedback on potential issues and thoughts first.
Furthermore, I expect little to no breaking changes for the user when switching to this implementation.
I documented the macro a bit in the
charming-derive/src/lib.rs
file. A well formatted version can be seen when usingcargo doc
. You can check what the macro expands to when usingcargo expand --test derive_test
in thecharming-derive
folder.Current implementation
Implementation with the macro
I also added two field attributes
charming_type
andcharming_skip_setter
, their uses can be seen belowThis is just a draft. I will implement more tests first and then open another PR where we derive the new macro on all applicable structs. Just want to get some feedback on potential issues and thoughts first.
Furthermore, I expect little to no breaking changes for the user when switching to this implementation.