qubit_metadata/schema/
definition.rs1use std::collections::BTreeMap;
12
13use qubit_common::DataType;
14use qubit_value::Value;
15use serde::{Deserialize, Serialize};
16
17use crate::schema::{MetadataField, MetadataSchemaBuilder, UnknownFieldPolicy};
18use crate::{Metadata, MetadataError, MetadataResult};
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub struct MetadataSchema {
27 fields: BTreeMap<String, MetadataField>,
29 unknown_field_policy: UnknownFieldPolicy,
31}
32
33impl MetadataSchema {
34 #[inline]
36 #[must_use]
37 pub fn builder() -> MetadataSchemaBuilder {
38 MetadataSchemaBuilder::default()
39 }
40
41 #[inline]
43 pub(crate) fn new(
44 fields: BTreeMap<String, MetadataField>,
45 unknown_field_policy: UnknownFieldPolicy,
46 ) -> Self {
47 Self {
48 fields,
49 unknown_field_policy,
50 }
51 }
52
53 #[inline]
55 #[must_use]
56 pub fn field(&self, key: &str) -> Option<&MetadataField> {
57 self.fields.get(key)
58 }
59
60 #[inline]
62 #[must_use]
63 pub fn field_type(&self, key: &str) -> Option<DataType> {
64 self.field(key).map(MetadataField::data_type)
65 }
66
67 #[inline]
69 #[must_use]
70 pub fn unknown_field_policy(&self) -> UnknownFieldPolicy {
71 self.unknown_field_policy
72 }
73
74 #[inline]
76 pub fn fields(&self) -> impl Iterator<Item = (&str, &MetadataField)> {
77 self.fields.iter().map(|(key, field)| (key.as_str(), field))
78 }
79
80 pub fn validate(&self, meta: &Metadata) -> MetadataResult<()> {
88 for (key, field) in &self.fields {
89 if field.is_required() && !meta.contains_key(key) {
90 return Err(MetadataError::MissingRequiredField {
91 key: key.clone(),
92 expected: field.data_type(),
93 });
94 }
95 }
96
97 for (key, value) in meta.iter() {
98 self.validate_entry(key, value)?;
99 }
100 Ok(())
101 }
102
103 pub(crate) fn validate_entry(&self, key: &str, value: &Value) -> MetadataResult<()> {
105 match self.field(key) {
106 Some(field) if field.data_type() != value.data_type() => Err(
107 MetadataError::type_mismatch(key, field.data_type(), value.data_type()),
108 ),
109 Some(_) => Ok(()),
110 None if matches!(self.unknown_field_policy, UnknownFieldPolicy::Reject) => {
111 Err(MetadataError::UnknownField {
112 key: key.to_string(),
113 })
114 }
115 None => Ok(()),
116 }
117 }
118}
119
120impl Default for MetadataSchema {
121 #[inline]
122 fn default() -> Self {
123 Self {
124 fields: BTreeMap::new(),
125 unknown_field_policy: UnknownFieldPolicy::Reject,
126 }
127 }
128}