use std::sync::Arc;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::de::{self, Deserializer};
use serde_json::Value;
use crate::Expr;
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)]
#[serde(remote = "Self", 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 value = Value::deserialize(deserializer)?;
if value.as_object().is_some_and(|map| map.contains_key("text")) {
return Label::deserialize(value).map_err(de::Error::custom);
}
Expr::from_value(value).map(Label::new).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
}
}