qubit_metadata/schema/
metadata_schema.rs1use std::collections::BTreeMap;
13
14use qubit_datatype::DataType;
15use qubit_value::Value;
16use serde::{
17 Deserialize,
18 Serialize,
19};
20
21use crate::schema::{
22 MetadataField,
23 MetadataSchemaBuilder,
24 UnknownFieldPolicy,
25};
26use crate::{
27 Metadata,
28 MetadataError,
29 MetadataResult,
30 MetadataValidationError,
31 MetadataValidationResult,
32};
33
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40pub struct MetadataSchema {
41 fields: BTreeMap<String, MetadataField>,
43 unknown_field_policy: UnknownFieldPolicy,
45}
46
47impl MetadataSchema {
48 #[inline]
50 #[must_use]
51 pub fn builder() -> MetadataSchemaBuilder {
52 MetadataSchemaBuilder::default()
53 }
54
55 #[inline]
57 pub(crate) fn new(
58 fields: BTreeMap<String, MetadataField>,
59 unknown_field_policy: UnknownFieldPolicy,
60 ) -> Self {
61 Self {
62 fields,
63 unknown_field_policy,
64 }
65 }
66
67 #[inline]
69 #[must_use]
70 pub fn field(&self, key: &str) -> Option<&MetadataField> {
71 self.fields.get(key)
72 }
73
74 #[inline]
76 #[must_use]
77 pub fn field_type(&self, key: &str) -> Option<DataType> {
78 self.field(key).map(MetadataField::data_type)
79 }
80
81 #[inline]
83 #[must_use]
84 pub fn unknown_field_policy(&self) -> UnknownFieldPolicy {
85 self.unknown_field_policy
86 }
87
88 #[inline]
90 pub fn fields(&self) -> impl Iterator<Item = (&str, &MetadataField)> {
91 self.fields.iter().map(|(key, field)| (key.as_str(), field))
92 }
93
94 pub fn validate(&self, meta: &Metadata) -> MetadataValidationResult<()> {
101 let mut issues = Vec::new();
102 for (key, field) in &self.fields {
103 if field.is_required() && !meta.contains_key(key) {
104 issues.push(MetadataError::MissingRequiredField {
105 key: key.clone(),
106 expected: field.data_type(),
107 });
108 }
109 }
110
111 for (key, value) in meta.iter() {
112 if let Err(error) = self.validate_entry(key, value) {
113 issues.push(error);
114 }
115 }
116 if let Some(error) = MetadataValidationError::from_issues(issues) {
117 Err(error)
118 } else {
119 Ok(())
120 }
121 }
122
123 pub(crate) fn validate_entry(&self, key: &str, value: &Value) -> MetadataResult<()> {
125 match self.field(key) {
126 Some(field) if field.data_type() != value.data_type() => Err(
127 MetadataError::type_mismatch(key, field.data_type(), value.data_type()),
128 ),
129 Some(_) => Ok(()),
130 None if matches!(self.unknown_field_policy, UnknownFieldPolicy::Reject) => {
131 Err(MetadataError::UnknownField {
132 key: key.to_string(),
133 })
134 }
135 None => Ok(()),
136 }
137 }
138}
139
140impl Default for MetadataSchema {
141 #[inline]
142 fn default() -> Self {
143 Self {
144 fields: BTreeMap::new(),
145 unknown_field_policy: UnknownFieldPolicy::Reject,
146 }
147 }
148}