use std::sync::Arc;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::de::{self, Deserializer};
use crate::Expr;
use crate::expr::form::Written;
#[derive(Clone, PartialEq, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(transform = text_or_options)]
pub struct Label {
pub(crate) text: Expr,
#[serde(default)]
pub(crate) size: Option<f32>,
#[serde(default)]
pub(crate) color: Option<Expr>,
#[serde(default)]
pub(crate) priority: Option<Expr>,
#[serde(default)]
pub(crate) max_width: Option<f32>,
#[serde(default)]
pub(crate) font: Option<Arc<str>>,
#[serde(default)]
pub(crate) max: Option<u32>,
}
impl<'de> Deserialize<'de> for Label {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Label, D::Error> {
let label = |written: Written| match written {
Written::Object(mut form) if form.text.is_some() => {
form.only("a label", &["text", "size", "color", "priority", "maxWidth", "font", "max"])?;
Ok(Label {
color: form.color()?,
text: form.text.expect("held"),
size: form.size,
priority: form.priority,
max_width: form.max_width,
font: form.font,
max: form.max,
})
}
written => written.expr().map(Label::new),
};
label(Written::deserialize(deserializer)?).map_err(de::Error::custom)
}
}
fn text_or_options(schema: &mut schemars::Schema) {
let options = std::mem::replace(schema, schemars::json_schema!({}));
*schema = schemars::json_schema!({ "anyOf": [{ "$ref": "#/$defs/Expr" }, options] });
}
impl Label {
pub fn new(text: impl Into<Expr>) -> Label {
Label { text: text.into(), size: None, color: None, priority: None, max_width: None, font: None, max: None }
}
#[must_use]
pub fn size(mut self, size: f32) -> Label {
self.size = Some(size);
self
}
#[must_use]
pub fn color(mut self, color: impl Into<Expr>) -> Label {
self.color = Some(color.into());
self
}
#[must_use]
pub fn priority(mut self, priority: impl Into<Expr>) -> Label {
self.priority = Some(priority.into());
self
}
#[must_use]
pub fn max_width(mut self, width: f32) -> Label {
self.max_width = Some(width);
self
}
#[must_use]
pub fn font(mut self, font: impl Into<Arc<str>>) -> Label {
self.font = Some(font.into());
self
}
#[must_use]
pub fn max(mut self, max: u32) -> Label {
self.max = Some(max);
self
}
}