+impl ObjectSchemaType for OneOfSchema {
+ fn description(&self) -> &'static str {
+ self.description
+ }
+
+ fn lookup(&self, key: &str) -> Option<(bool, &Schema)> {
+ OneOfSchema::lookup(self, key)
+ }
+
+ fn properties(&self) -> ObjectPropertyIterator {
+ ObjectPropertyIterator::OneOf(OneOfPropertyIterator {
+ type_property_entry: self.type_property_entry,
+ schemas: self.list.iter(),
+ done: HashSet::new(),
+ nested: None,
+ })
+ }
+
+ fn additional_properties(&self) -> bool {
+ true
+ }
+
+ fn default_key(&self) -> Option<&'static str> {
+ None
+ }
+
+ fn verify_json(&self, data: &Value) -> Result<(), Error> {
+ let map = match data {
+ Value::Object(ref map) => map,
+ Value::Array(_) => bail!("Expected object - got array."),
+ _ => bail!("Expected object - got scalar value."),
+ };
+
+ // Without the type we also cannot verify anything else...:
+ let variant = match map.get(self.type_property()) {
+ None => bail!("Missing '{}' property", self.type_property()),
+ Some(Value::String(v)) => v,
+ _ => bail!("Expected string in '{}'", self.type_property()),
+ };
+
+ let schema = self
+ .lookup_variant(variant)
+ .ok_or_else(|| format_err!("invalid '{}': {}", self.type_property(), variant))?;
+
+ schema.verify_json(data)
+ }
+}
+
+#[doc(hidden)]
+pub struct OneOfPropertyIterator {
+ type_property_entry: &'static SchemaPropertyEntry,
+ schemas: std::slice::Iter<'static, (&'static str, &'static Schema)>,
+ done: HashSet<&'static str>,
+ nested: Option<Box<ObjectPropertyIterator>>,
+}
+
+impl Iterator for OneOfPropertyIterator {
+ type Item = &'static SchemaPropertyEntry;
+
+ fn next(&mut self) -> Option<&'static SchemaPropertyEntry> {
+ if self.done.insert(self.type_property_entry.0) {
+ return Some(self.type_property_entry);
+ }
+
+ loop {
+ match self.nested.as_mut().and_then(Iterator::next) {
+ Some(item) => {
+ if !self.done.insert(item.0) {
+ continue;
+ }
+ return Some(item);
+ }
+ None => self.nested = None,
+ }
+
+ self.nested = Some(Box::new(
+ self.schemas
+ .next()?
+ .1
+ .any_object()
+ .expect("non-object-schema in `OneOfSchema`")
+ .properties(),
+ ));
+ }
+ }
+}
+