1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use serde::{Deserialize, Serialize};

use crate::{is_false, Type};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct Field {
  /// The name of the field.
  pub name: String,

  /// The type of the field.
  #[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,

  /// Whether the field is required.
  #[cfg(feature = "value")]
  #[serde(default, skip_serializing_if = "Option::is_none")]
  pub default: Option<serde_json::Value>,

  /// Whether the field is required.
  #[serde(default, skip_serializing_if = "is_false")]
  pub required: bool,

  /// The description of the field.
  #[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,
    }
  }

  /// Get the name of the field
  #[must_use]
  pub fn name(&self) -> &str {
    &self.name
  }

  /// Get the type of the field
  pub const fn ty(&self) -> &Type {
    &self.ty
  }

  /// Get the description of the field
  #[must_use]
  pub fn description(&self) -> Option<&str> {
    self.description.as_deref()
  }

  /// Get the default value of the field
  #[must_use]
  #[cfg(feature = "value")]
  pub const fn default(&self) -> Option<&serde_json::Value> {
    self.default.as_ref()
  }

  /// Get whether the field is required
  #[must_use]
  pub const fn required(&self) -> bool {
    self.required
  }

  /// Consume the [Field] and return a [FieldValue] with the given value.
  #[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)
  }
}

/// A field and its value.
#[cfg(feature = "value")]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct FieldValue {
  /// The field.
  pub field: Field,
  /// The value of the field.
  pub value: serde_json::Value,
}

#[cfg(feature = "value")]
impl FieldValue {
  /// Create a new field value.
  #[must_use]
  pub const fn new(field: Field, value: serde_json::Value) -> Self {
    Self { field, value }
  }

  /// Get the name of the field
  #[must_use]
  pub fn name(&self) -> &str {
    &self.field.name
  }

  /// Get the type of the field
  pub const fn signature(&self) -> &Type {
    &self.field.ty
  }

  /// Get the value of the field
  #[must_use]
  pub const fn value(&self) -> &serde_json::Value {
    &self.value
  }
}