use serde::{Deserialize, Serialize};
use crate::{is_false, Type};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct Field {
pub name: String,
#[serde(rename = "type")]
#[cfg_attr(feature = "parser", serde(deserialize_with = "crate::types::deserialize_type"))]
#[cfg_attr(
feature = "yaml",
serde(serialize_with = "serde_yaml::with::singleton_map::serialize")
)]
pub ty: Type,
#[cfg(feature = "value")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "is_false")]
pub required: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
impl Field {
pub fn new<T: Into<String>>(name: T, ty: Type) -> Self {
Self::new_with_description(name, ty, None)
}
pub fn new_with_description<T: Into<String>>(name: T, ty: Type, desc: Option<String>) -> Self {
Self {
name: name.into(),
description: desc,
#[cfg(feature = "value")]
default: None,
required: !matches!(ty, Type::Optional { .. }),
ty,
}
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
pub const fn ty(&self) -> &Type {
&self.ty
}
#[must_use]
pub fn description(&self) -> Option<&str> {
self.description.as_deref()
}
#[must_use]
#[cfg(feature = "value")]
pub const fn default(&self) -> Option<&serde_json::Value> {
self.default.as_ref()
}
#[must_use]
pub const fn required(&self) -> bool {
self.required
}
#[must_use]
#[cfg(feature = "value")]
pub fn with_value(self, value: impl Into<serde_json::Value>) -> FieldValue {
FieldValue::new(self, value.into())
}
}
impl std::fmt::Display for Field {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.name)?;
f.write_str(": ")?;
self.ty.fmt(f)
}
}
#[cfg(feature = "value")]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct FieldValue {
pub field: Field,
pub value: serde_json::Value,
}
#[cfg(feature = "value")]
impl FieldValue {
#[must_use]
pub const fn new(field: Field, value: serde_json::Value) -> Self {
Self { field, value }
}
#[must_use]
pub fn name(&self) -> &str {
&self.field.name
}
pub const fn signature(&self) -> &Type {
&self.field.ty
}
#[must_use]
pub const fn value(&self) -> &serde_json::Value {
&self.value
}
}