use super::{BTreeMap, ValidationOptions, Value};
#[derive(Clone)]
pub struct StringSchema {
schema: BTreeMap<String, Value>,
}
impl StringSchema {
fn new() -> Self {
let mut schema = BTreeMap::new();
schema.insert("type".into(), Value::String("string".into()));
Self { schema }
}
#[must_use]
pub fn min_len(mut self, n: usize) -> Self {
self.schema
.insert("minLength".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn max_len(mut self, n: usize) -> Self {
self.schema
.insert("maxLength".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn len(self, n: usize) -> Self {
self.min_len(n).max_len(n)
}
#[must_use]
pub fn pattern(mut self, re: &str) -> Self {
self.schema
.insert("pattern".into(), Value::String(re.into()));
self
}
#[must_use]
pub fn format(mut self, f: &str) -> Self {
self.schema.insert("format".into(), Value::String(f.into()));
self
}
#[must_use]
pub fn email(self) -> Self {
self.format("email")
}
#[must_use]
pub fn uri(self) -> Self {
self.format("uri")
}
#[must_use]
pub fn uuid(self) -> Self {
self.format("uuid")
}
#[must_use]
pub fn date_time(self) -> Self {
self.format("date-time")
}
#[must_use]
pub fn hostname(self) -> Self {
self.format("hostname")
}
#[must_use]
pub fn ipv4(self) -> Self {
self.format("ipv4")
}
#[must_use]
pub fn ipv6(self) -> Self {
self.format("ipv6")
}
#[must_use]
pub fn base64(self) -> Self {
self.format("base64")
}
#[must_use]
pub fn enum_values(mut self, vals: Vec<String>) -> Self {
self.schema.insert(
"enum".into(),
Value::Array(vals.into_iter().map(Value::String).collect()),
);
self
}
#[must_use]
pub fn optional(mut self) -> Self {
let inner = Value::Object(
self.schema
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect(),
);
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 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 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
}
}
#[derive(Clone)]
pub struct IntegerSchema {
schema: BTreeMap<String, Value>,
}
impl IntegerSchema {
fn new() -> Self {
let mut schema = BTreeMap::new();
schema.insert("type".into(), Value::String("integer".into()));
Self { schema }
}
#[must_use]
pub fn min(mut self, n: i64) -> Self {
self.schema
.insert("minimum".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn max(mut self, n: i64) -> Self {
self.schema
.insert("maximum".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn exclusive_min(mut self, n: i64) -> Self {
self.schema
.insert("exclusiveMinimum".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn exclusive_max(mut self, n: i64) -> Self {
self.schema
.insert("exclusiveMaximum".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn multiple_of(mut self, n: i64) -> Self {
self.schema
.insert("multipleOf".into(), Value::Number(n.into()));
self
}
#[must_use]
pub fn positive(self) -> Self {
self.exclusive_min(0)
}
#[must_use]
pub fn nonnegative(self) -> Self {
self.min(0)
}
#[must_use]
pub fn negative(self) -> Self {
self.exclusive_max(0)
}
#[must_use]
pub fn nonpositive(self) -> Self {
self.max(0)
}
#[must_use]
pub fn enum_values(mut self, vals: Vec<i64>) -> Self {
self.schema.insert(
"enum".into(),
Value::Array(vals.into_iter().map(|n| Value::Number(n.into())).collect()),
);
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 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 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
}
}
#[derive(Clone)]
pub struct NumberSchema {
schema: BTreeMap<String, Value>,
}
impl NumberSchema {
fn new() -> Self {
let mut schema = BTreeMap::new();
schema.insert("type".into(), Value::String("number".into()));
Self { schema }
}
#[must_use]
pub fn min(mut self, n: f64) -> Self {
self.schema.insert(
"minimum".into(),
serde_json::Number::from_f64(n).map_or(Value::Null, Value::Number),
);
self
}
#[must_use]
pub fn max(mut self, n: f64) -> Self {
self.schema.insert(
"maximum".into(),
serde_json::Number::from_f64(n).map_or(Value::Null, Value::Number),
);
self
}
#[must_use]
pub fn exclusive_min(mut self, n: f64) -> Self {
self.schema.insert(
"exclusiveMinimum".into(),
serde_json::Number::from_f64(n).map_or(Value::Null, Value::Number),
);
self
}
#[must_use]
pub fn exclusive_max(mut self, n: f64) -> Self {
self.schema.insert(
"exclusiveMaximum".into(),
serde_json::Number::from_f64(n).map_or(Value::Null, Value::Number),
);
self
}
#[must_use]
pub fn multiple_of(mut self, n: f64) -> Self {
self.schema.insert(
"multipleOf".into(),
serde_json::Number::from_f64(n).map_or(Value::Null, Value::Number),
);
self
}
#[must_use]
pub fn positive(self) -> Self {
self.exclusive_min(0.0)
}
#[must_use]
pub fn nonnegative(self) -> Self {
self.min(0.0)
}
#[must_use]
pub fn negative(self) -> Self {
self.exclusive_max(0.0)
}
#[must_use]
pub fn nonpositive(self) -> Self {
self.max(0.0)
}
#[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 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 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
}
}
#[derive(Clone)]
pub struct BooleanSchema {
schema: BTreeMap<String, Value>,
}
impl BooleanSchema {
fn new() -> Self {
let mut schema = BTreeMap::new();
schema.insert("type".into(), Value::String("boolean".into()));
Self { schema }
}
#[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
}
}
#[derive(Clone)]
pub struct NullSchema {
schema: BTreeMap<String, Value>,
}
impl NullSchema {
fn new() -> Self {
let mut schema = BTreeMap::new();
schema.insert("type".into(), Value::String("null".into()));
Self { schema }
}
#[must_use]
pub fn description(mut self, desc: &str) -> Self {
self.schema
.insert("description".into(), Value::String(desc.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 string() -> StringSchema {
StringSchema::new()
}
#[must_use]
pub fn integer() -> IntegerSchema {
IntegerSchema::new()
}
#[must_use]
pub fn number() -> NumberSchema {
NumberSchema::new()
}
#[must_use]
pub fn boolean() -> BooleanSchema {
BooleanSchema::new()
}
#[must_use]
pub fn null() -> NullSchema {
NullSchema::new()
}
impl From<StringSchema> for Value {
fn from(builder: StringSchema) -> Self {
builder.build_schema()
}
}
impl From<IntegerSchema> for Value {
fn from(builder: IntegerSchema) -> Self {
builder.build_schema()
}
}
impl From<NumberSchema> for Value {
fn from(builder: NumberSchema) -> Self {
builder.build_schema()
}
}
impl From<BooleanSchema> for Value {
fn from(builder: BooleanSchema) -> Self {
builder.build_schema()
}
}
impl From<NullSchema> for Value {
fn from(builder: NullSchema) -> Self {
builder.build_schema()
}
}