use serde::Serialize;
#[derive(Debug, PartialEq, Clone)]
pub struct Options {
comment: String,
tags: Vec<String>,
scopes: Vec<String>,
expiration: Option<Expiration>,
}
#[derive(Debug, PartialEq, Clone)]
enum Expiration {
ExpirationDate(String),
TimeToLiveInSeconds(usize),
}
#[derive(Debug, PartialEq, Clone)]
pub struct OptionsBuilder(Options);
#[derive(Serialize)]
pub(crate) struct SerializableOptions<'a> {
comment: &'a String,
#[serde(skip_serializing_if = "Vec::is_empty")]
tags: &'a Vec<String>,
scopes: &'a Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
expiration_date: Option<&'a String>,
#[serde(skip_serializing_if = "Option::is_none")]
time_to_live_in_seconds: Option<usize>,
}
impl Options {
pub fn builder<'a>(
comment: impl Into<String>,
scopes: impl IntoIterator<Item = &'a str>,
) -> OptionsBuilder {
OptionsBuilder::new(comment, scopes)
}
pub fn json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string(&SerializableOptions::from(self))
}
}
impl OptionsBuilder {
pub fn new<'a>(comment: impl Into<String>, scopes: impl IntoIterator<Item = &'a str>) -> Self {
Self(Options {
comment: comment.into(),
tags: Vec::new(),
scopes: scopes.into_iter().map(String::from).collect(),
expiration: None,
})
}
pub fn comment(mut self, comment: impl Into<String>) -> Self {
self.0.comment = comment.into();
self
}
pub fn tag<'a>(mut self, tags: impl IntoIterator<Item = &'a str>) -> Self {
self.0.tags.extend(tags.into_iter().map(String::from));
self
}
pub fn scopes<'a>(mut self, scopes: impl IntoIterator<Item = &'a str>) -> Self {
self.0.scopes.extend(scopes.into_iter().map(String::from));
self
}
pub fn expiration_date(mut self, expiration_date: impl Into<String>) -> Self {
self.0.expiration = Some(Expiration::ExpirationDate(expiration_date.into()));
self
}
pub fn time_to_live_in_seconds(mut self, time_to_live_in_seconds: usize) -> Self {
self.0.expiration = Some(Expiration::TimeToLiveInSeconds(time_to_live_in_seconds));
self
}
pub fn build(self) -> Options {
self.0
}
}
impl<'a> From<&'a Options> for SerializableOptions<'a> {
fn from(options: &'a Options) -> Self {
let Options {
comment,
tags,
scopes,
expiration,
} = options;
let mut serializable_options = Self {
comment,
tags,
scopes,
expiration_date: None,
time_to_live_in_seconds: None,
};
match expiration {
Some(Expiration::ExpirationDate(expiration_date)) => {
serializable_options.expiration_date = Some(expiration_date);
}
Some(Expiration::TimeToLiveInSeconds(time_to_live_in_seconds)) => {
serializable_options.time_to_live_in_seconds = Some(*time_to_live_in_seconds);
}
None => {}
};
serializable_options
}
}