96 lines
2.6 KiB
Rust
96 lines
2.6 KiB
Rust
use crate::database::object::*;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::Value;
|
|
|
|
#[derive(Debug, Clone, Serialize, Default)]
|
|
pub struct Schema {
|
|
#[serde(flatten)]
|
|
pub obj: SchemaObject,
|
|
#[serde(skip)]
|
|
pub always_fail: bool,
|
|
}
|
|
|
|
impl std::ops::Deref for Schema {
|
|
type Target = SchemaObject;
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.obj
|
|
}
|
|
}
|
|
impl std::ops::DerefMut for Schema {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.obj
|
|
}
|
|
}
|
|
|
|
impl Schema {
|
|
/// Returns true if the schema acts purely as a type pointer (composition without overriding constraints)
|
|
pub fn is_proxy(&self) -> bool {
|
|
self.obj.properties.is_none()
|
|
&& self.obj.pattern_properties.is_none()
|
|
&& self.obj.additional_properties.is_none()
|
|
&& self.obj.required.is_none()
|
|
&& self.obj.dependencies.is_none()
|
|
&& self.obj.items.is_none()
|
|
&& self.obj.prefix_items.is_none()
|
|
&& self.obj.contains.is_none()
|
|
&& self.obj.format.is_none()
|
|
&& self.obj.enum_.is_none()
|
|
&& self.obj.const_.is_none()
|
|
&& self.obj.cases.is_none()
|
|
&& self.obj.one_of.is_none()
|
|
&& self.obj.not.is_none()
|
|
&& self.obj.family.is_none()
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for Schema {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
let v: Value = Deserialize::deserialize(deserializer)?;
|
|
|
|
if let Some(b) = v.as_bool() {
|
|
let mut obj = SchemaObject::default();
|
|
if b {
|
|
obj.extensible = Some(true);
|
|
}
|
|
return Ok(Schema {
|
|
obj,
|
|
always_fail: !b,
|
|
});
|
|
}
|
|
let mut obj: SchemaObject =
|
|
serde_json::from_value(v.clone()).map_err(serde::de::Error::custom)?;
|
|
|
|
// If a schema is effectively empty (except for potentially carrying an ID),
|
|
// it functions as a boolean `true` schema in Draft2020 which means it should not
|
|
// restrict additional properties natively
|
|
let is_empty = obj.type_.is_none()
|
|
&& obj.properties.is_none()
|
|
&& obj.pattern_properties.is_none()
|
|
&& obj.additional_properties.is_none()
|
|
&& obj.required.is_none()
|
|
&& obj.dependencies.is_none()
|
|
&& obj.items.is_none()
|
|
&& obj.prefix_items.is_none()
|
|
&& obj.contains.is_none()
|
|
&& obj.format.is_none()
|
|
&& obj.enum_.is_none()
|
|
&& obj.const_.is_none()
|
|
&& obj.cases.is_none()
|
|
&& obj.one_of.is_none()
|
|
&& obj.not.is_none()
|
|
&& obj.family.is_none();
|
|
|
|
if is_empty && obj.extensible.is_none() {
|
|
obj.extensible = Some(true);
|
|
}
|
|
|
|
Ok(Schema {
|
|
obj,
|
|
always_fail: false,
|
|
})
|
|
}
|
|
}
|