use super::{BTreeMap, ValidationOptions, Value};
#[derive(Clone)]
pub struct ArraySchema {
schema: BTreeMap<String, Value>,
}
impl ArraySchema {
fn new() -> Self {
let mut schema = BTreeMap::new();
schema.insert("type".into(), Value::String("array".into()));
Self { schema }
}
#[must_use]
pub fn items(mut self, schema: impl Into<Value>) -> Self {
self.schema.insert("items".into(), schema.into());
self
}
#[must_use]
pub fn prefix_items(mut self, schemas: Vec<impl Into<Value>>) -> Self {
self.schema.insert(
"prefixItems".into(),
Value::Array(schemas.into_iter().map(Into::into).collect()),
);
self
}
#[must_use]
pub fn additional_items(mut self, schema: impl Into<Value>) -> Self {
self.schema.insert("additionalItems".into(), schema.into());
self
}
#[must_use]
pub fn min_items(mut self, n: usize) -> Self {
self.schema
.insert("minItems".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn max_items(mut self, n: usize) -> Self {
self.schema
.insert("maxItems".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn len(self, n: usize) -> Self {
self.min_items(n).max_items(n)
}
#[must_use]
pub fn unique(mut self) -> Self {
self.schema.insert("uniqueItems".into(), Value::Bool(true));
self
}
#[must_use]
pub fn nonempty(self) -> Self {
self.min_items(1)
}
#[must_use]
pub fn contains(mut self, schema: impl Into<Value>) -> Self {
self.schema.insert("contains".into(), schema.into());
self
}
#[must_use]
pub fn min_contains(mut self, n: u64) -> Self {
self.schema
.insert("minContains".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn max_contains(mut self, n: u64) -> Self {
self.schema
.insert("maxContains".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn description(mut self, desc: &str) -> Self {
self.schema
.insert("description".into(), Value::String(desc.into()));
self
}
#[must_use]
pub fn default(mut self, value: Value) -> Self {
self.schema.insert("default".into(), value);
self
}
#[must_use]
pub fn optional(mut self) -> Self {
let inner = self.build_schema();
self.schema.clear();
let mut null_schema = serde_json::Map::default();
null_schema.insert("type".into(), Value::String("null".into()));
self.schema.insert(
"anyOf".into(),
Value::Array(vec![inner, Value::Object(null_schema)]),
);
self
}
#[must_use]
pub fn nullable(mut self) -> Self {
if let Some(Value::String(t)) = self.schema.get("type").cloned() {
self.schema.insert(
"type".into(),
Value::Array(vec![Value::String(t), Value::String("null".into())]),
);
}
self
}
#[must_use]
pub fn build_schema(&self) -> Value {
Value::Object(
self.schema
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect(),
)
}
#[must_use]
pub fn build(self) -> ValidationOptions {
let mut options = ValidationOptions::new();
options.schema = Some(self.build_schema());
options
}
}
#[must_use]
pub fn array() -> ArraySchema {
ArraySchema::new()
}
#[must_use]
pub fn array_of(schema: impl Into<Value>) -> ArraySchema {
array().items(schema)
}
impl From<ArraySchema> for Value {
fn from(builder: ArraySchema) -> Self {
builder.build_schema()
}
}