use bson::{ Bson, Document };
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Bound {
Unbounded,
Inclusive(f64),
Exclusive(f64),
}
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Bounds {
pub lower: Bound,
pub upper: Bound,
}
#[doc(hidden)]
pub fn extend_schema_with_bounds(mut schema: Document, bounds: Bounds) -> Document {
match bounds.lower {
Bound::Unbounded => {},
Bound::Inclusive(minimum) => {
schema.insert("minimum", minimum);
schema.insert("exclusiveMinimum", false);
},
Bound::Exclusive(minimum) => {
schema.insert("minimum", minimum);
schema.insert("exclusiveMinimum", true);
},
}
match bounds.upper {
Bound::Unbounded => {},
Bound::Inclusive(maximum) => {
schema.insert("maximum", maximum);
schema.insert("exclusiveMaximum", false);
},
Bound::Exclusive(maximum) => {
schema.insert("maximum", maximum);
schema.insert("exclusiveMaximum", true);
},
}
schema
}
#[doc(hidden)]
pub fn extend_schema_with_tag(schema: Document, tag: &str, variant: &str) -> Document {
if schema_is_struct(&schema) {
extend_struct_schema_with_tag(schema, tag, variant)
} else if schema_is_map(&schema) {
extend_map_schema_with_tag(schema, tag, variant)
} else if schema_is_enum(&schema) {
extend_enum_schema_with_tag(schema, tag, variant)
} else {
panic!("newtype variant doesn't describe a struct, a map, or an enum?!")
}
}
fn schema_is_struct(doc: &Document) -> bool {
doc.get_str("type") == Ok("object")
&&
doc.get_document("properties").is_ok()
}
fn schema_is_map(doc: &Document) -> bool {
doc.get_str("type") == Ok("object")
&&
doc.get_document("additionalProperties").is_ok()
}
fn schema_is_enum(doc: &Document) -> bool {
doc.get_array("anyOf").is_ok()
}
fn extend_struct_schema_with_tag(mut schema: Document, tag: &str, variant: &str) -> Document {
let mut required = match schema.remove("required") {
Some(Bson::Array(arr)) => arr,
Some(_) => panic!("`required` is not an array in struct schema?!"),
None => panic!("`required` key not found in struct schema?!"),
};
let mut properties = match schema.remove("properties") {
Some(Bson::Document(doc)) => doc,
Some(_) => panic!("`properties` is not a document in struct schema?!"),
None => panic!("`properties` key not found in struct schema?!"),
};
required.push(tag.into());
properties.insert(tag, doc!{ "enum": [ variant ] });
schema.insert("required", required);
schema.insert("properties", properties);
schema
}
fn extend_map_schema_with_tag(mut schema: Document, tag: &str, variant: &str) -> Document {
schema.insert("required", vec![ tag.into() ]);
schema.insert("properties", doc!{ tag: { "enum": [ variant ] } });
schema
}
fn extend_enum_schema_with_tag(_schema: Document, _tag: &str, _variant: &str) -> Document {
unimplemented!("internally-tagged newtype variants around enums are not yet supported")
}