From aaeb46db0d1c17c2bb58fd3ec11e73a2501e6f60 Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Sun, 20 Oct 2019 22:34:25 +0100 Subject: [PATCH] Add more doc comments --- schemars/src/flatten.rs | 1 + schemars/src/gen.rs | 49 +++++++++++- schemars/src/schema.rs | 160 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 199 insertions(+), 11 deletions(-) diff --git a/schemars/src/flatten.rs b/schemars/src/flatten.rs index a34cb76..31524c4 100644 --- a/schemars/src/flatten.rs +++ b/schemars/src/flatten.rs @@ -2,6 +2,7 @@ use crate::schema::*; use crate::{Map, Set}; impl Schema { + #[doc(hidden)] pub fn flatten(self, other: Self) -> Schema { if is_null_type(&self) { return other; diff --git a/schemars/src/gen.rs b/schemars/src/gen.rs index e6d6af2..160623e 100644 --- a/schemars/src/gen.rs +++ b/schemars/src/gen.rs @@ -77,14 +77,14 @@ impl SchemaSettings { /// /// # Example /// ``` -/// use schemars::{schema_for, JsonSchema}; +/// use schemars::{JsonSchema, gen::SchemaGenerator}; /// /// #[derive(JsonSchema)] /// struct MyStruct { /// foo: i32, /// } /// -/// let gen = SchemaGenerator::new(SchemaSettings::new()); +/// let gen = SchemaGenerator::default(); /// let schema = gen.into_root_schema_for::(); /// ``` #[derive(Debug, Default, Clone)] @@ -103,6 +103,16 @@ impl SchemaGenerator { } /// Borrows the [`SchemaSettings`] being used by this `SchemaGenerator`. + /// + /// # Example + /// ``` + /// use schemars::gen::SchemaGenerator; + /// + /// let gen = SchemaGenerator::default(); + /// let settings = gen.settings(); + /// + /// assert_eq!(settings.option_add_null_type, true); + /// ``` pub fn settings(&self) -> &SchemaSettings { &self.settings } @@ -167,7 +177,7 @@ impl SchemaGenerator { &self.definitions } - /// Consumes the generator and returns the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated. + /// Consumes `self` and returns the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated. /// /// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas /// themselves. @@ -175,6 +185,11 @@ impl SchemaGenerator { self.definitions } + /// Generates a root JSON Schema for the type `T`. + /// + /// If `T`'s schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will + /// add them to the `SchemaGenerator`'s schema definitions and include them in the returned `SchemaObject`'s + /// [`definitions`](../schema/struct.Metadata.html#structfield.definitions) pub fn root_schema_for(&mut self) -> SchemaObject { let mut schema: SchemaObject = T::json_schema(self).into(); let metadata = schema.metadata(); @@ -184,6 +199,10 @@ impl SchemaGenerator { schema } + /// Consumes `self` and generates a root JSON Schema for the type `T`. + /// + /// If `T`'s schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will + /// include them in the returned `SchemaObject`'s [`definitions`](../schema/struct.Metadata.html#structfield.definitions) pub fn into_root_schema_for(mut self) -> SchemaObject { let mut schema: SchemaObject = T::json_schema(&mut self).into(); let metadata = schema.metadata(); @@ -193,6 +212,30 @@ impl SchemaGenerator { schema } + /// Attemps to find the schema that the given `schema` is referencing. + /// + /// If the given `schema` has a [`$ref`](../schema/struct.SchemaObject.html#structfield.reference) property which refers + /// to another schema in `self`'s schema definitions, the referenced schema will be returned. Otherwise, returns `None`. + /// + /// # Example + /// ``` + /// use schemars::{JsonSchema, gen::SchemaGenerator}; + /// + /// #[derive(JsonSchema)] + /// struct MyStruct { + /// foo: i32, + /// } + /// + /// let mut gen = SchemaGenerator::default(); + /// let ref_schema = gen.subschema_for::(); + /// + /// assert!(ref_schema.is_ref()); + /// + /// let dereferenced = gen.dereference(&ref_schema); + /// + /// assert!(dereferenced.is_some()); + /// assert!(!dereferenced.unwrap().is_ref()); + /// ``` pub fn dereference<'a>(&'a self, schema: &Schema) -> Option<&'a Schema> { match schema { Schema::Object(SchemaObject { diff --git a/schemars/src/schema.rs b/schemars/src/schema.rs index 1b3837f..bfad05c 100644 --- a/schemars/src/schema.rs +++ b/schemars/src/schema.rs @@ -3,19 +3,33 @@ use crate::{JsonSchema, Map, Set}; use serde::{Deserialize, Serialize}; use serde_json::Value; +/// A JSON Schema. #[allow(clippy::large_enum_variant)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)] #[serde(untagged)] pub enum Schema { + /// A trivial boolean JSON Schema. + /// + /// The schema `true` matches everything (always passes validation), whereas the schema `false` + /// matches nothing (always fails validation). Bool(bool), + /// A JSON Schema object. Object(SchemaObject), } impl Schema { + /// Creates a new `$ref` schema. + /// + /// The given reference string should be a URI reference. This will usually be a JSON Pointer + /// in [URI Fragment representation](https://tools.ietf.org/html/rfc6901#section-6). pub fn new_ref(reference: String) -> Self { SchemaObject::new_ref(reference).into() } + /// Returns `true` if `self` is a `$ref` schema. + /// + /// If `self` is a [`SchemaObject`] with `Some` [`reference`](struct.SchemaObject.html#structfield.reference) set, this returns `true`. + /// Otherwise, returns `false`. pub fn is_ref(&self) -> bool { match self { Schema::Object(o) => o.is_ref(), @@ -80,6 +94,14 @@ where macro_rules! get_or_insert_default_fn { ($name:ident, $ret:path) => { + get_or_insert_default_fn!( + concat!("Returns a mutable reference to this schema's [`", stringify!($ret), "`](#structfield.", stringify!($name), "), creating it if it was `None`."), + $name, + $ret + ); + }; + ($doc:expr, $name:ident, $ret:path) => { + #[doc = $doc] pub fn $name(&mut self) -> &mut $ret { self.$name.get_or_insert_with(Default::default) } @@ -87,6 +109,10 @@ macro_rules! get_or_insert_default_fn { } impl SchemaObject { + /// Creates a new `$ref` schema. + /// + /// The given reference string should be a URI reference. This will usually be a JSON Pointer + /// in [URI Fragment representation](https://tools.ietf.org/html/rfc6901#section-6). pub fn new_ref(reference: String) -> Self { SchemaObject { reference: Some(reference), @@ -94,15 +120,12 @@ impl SchemaObject { } } + /// Returns `true` if `self` is a `$ref` schema. + /// + /// If `self` has `Some` [`reference`](struct.SchemaObject.html#structfield.reference) set, this returns `true`. + /// Otherwise, returns `false`. pub fn is_ref(&self) -> bool { - if self.reference.is_none() { - return false; - } - let only_ref = SchemaObject { - reference: self.reference.clone(), - ..Default::default() - }; - *self == only_ref + self.reference.is_some() } get_or_insert_default_fn!(metadata, Metadata); @@ -129,25 +152,57 @@ impl From for SchemaObject { } } +/// Properties which annotate a [`SchemaObject`] which typically have no effect when an object is being validated against the schema. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)] #[serde(rename_all = "camelCase", default)] pub struct Metadata { + /// The `$schema` keyword. + /// + /// This should be `Some` on a root schema, and `None` on subschemas. + /// + /// See [JSON Schema 8.1.1. The "$schema" Keyword](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.1.1). #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] pub schema: Option, + /// The `$id` keyword. + /// + /// See [JSON Schema 8.2.2. The "$id" Keyword](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.2). #[serde(rename = "$id", skip_serializing_if = "Option::is_none")] pub id: Option, + /// The `title` keyword. + /// + /// See [JSON Schema Validation 9.1. "title" and "description"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.1). #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, + /// The `description` keyword. + /// + /// See [JSON Schema Validation 9.1. "title" and "description"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.1). #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, + /// The `$defs` keyword. + /// + /// This is currently serialized as `definitions` for backwards compatibility. + /// + /// See [JSON Schema 8.2.5. Schema Re-Use With "$defs"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.5). #[serde(alias = "$defs", skip_serializing_if = "Map::is_empty")] pub definitions: Map, + /// The `default` keyword. + /// + /// See [JSON Schema Validation 9.2. "default"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.2). #[serde(skip_serializing_if = "Option::is_none")] pub default: Option, + /// The `deprecated` keyword. + /// + /// See [JSON Schema Validation 9.3. "deprecated"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.3). #[serde(skip_serializing_if = "is_false")] pub deprecated: bool, + /// The `readOnly` keyword. + /// + /// See [JSON Schema Validation 9.4. "readOnly" and "writeOnly"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.4). #[serde(skip_serializing_if = "is_false")] pub read_only: bool, + /// The `writeOnly` keyword. + /// + /// See [JSON Schema Validation 9.4. "readOnly" and "writeOnly"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-9.4). #[serde(skip_serializing_if = "is_false")] pub write_only: bool, } @@ -157,83 +212,172 @@ fn is_false(b: &bool) -> bool { !b } +/// Properties of a [`SchemaObject`] which define validation assertions in terms of other schemas. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)] #[serde(rename_all = "camelCase", default)] pub struct SubschemaValidation { + /// The `allOf` keyword. + /// + /// See [JSON Schema 9.2.1.1. "allOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.1). #[serde(skip_serializing_if = "Option::is_none")] pub all_of: Option>, + /// The `anyOf` keyword. + /// + /// See [JSON Schema 9.2.1.2. "anyOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.2). #[serde(skip_serializing_if = "Option::is_none")] pub any_of: Option>, + /// The `oneOf` keyword. + /// + /// See [JSON Schema 9.2.1.3. "oneOf"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.3). #[serde(skip_serializing_if = "Option::is_none")] pub one_of: Option>, + /// The `not` keyword. + /// + /// See [JSON Schema 9.2.1.4. "not"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.1.4). #[serde(skip_serializing_if = "Option::is_none")] pub not: Option>, + /// The `if` keyword. + /// + /// See [JSON Schema 9.2.2.1. "if"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.1). #[serde(rename = "if", skip_serializing_if = "Option::is_none")] pub if_schema: Option>, + /// The `then` keyword. + /// + /// See [JSON Schema 9.2.2.2. "then"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.2). #[serde(rename = "then", skip_serializing_if = "Option::is_none")] pub then_schema: Option>, + /// The `else` keyword. + /// + /// See [JSON Schema 9.2.2.3. "else"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.2.2.3). #[serde(rename = "else", skip_serializing_if = "Option::is_none")] pub else_schema: Option>, } +/// Properties of a [`SchemaObject`] which define validation assertions for numbers. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)] #[serde(rename_all = "camelCase", default)] pub struct NumberValidation { + /// The `multipleOf` keyword. + /// + /// See [JSON Schema Validation 6.2.1. "multipleOf"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.1). #[serde(skip_serializing_if = "Option::is_none")] pub multiple_of: Option, + /// The `maximum` keyword. + /// + /// See [JSON Schema Validation 6.2.2. "maximum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.2). #[serde(skip_serializing_if = "Option::is_none")] pub maximum: Option, + /// The `exclusiveMaximum` keyword. + /// + /// See [JSON Schema Validation 6.2.3. "exclusiveMaximum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.3). #[serde(skip_serializing_if = "Option::is_none")] pub exclusive_maximum: Option, + /// The `minimum` keyword. + /// + /// See [JSON Schema Validation 6.2.4. "minimum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.4). #[serde(skip_serializing_if = "Option::is_none")] pub minimum: Option, + /// The `exclusiveMinimum` keyword. + /// + /// See [JSON Schema Validation 6.2.5. "exclusiveMinimum"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.2.5). #[serde(skip_serializing_if = "Option::is_none")] pub exclusive_minimum: Option, } +/// Properties of a [`SchemaObject`] which define validation assertions for strings. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)] #[serde(rename_all = "camelCase", default)] pub struct StringValidation { + /// The `maxLength` keyword. + /// + /// See [JSON Schema Validation 6.3.1. "maxLength"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.1). #[serde(skip_serializing_if = "Option::is_none")] pub max_length: Option, + /// The `minLength` keyword. + /// + /// See [JSON Schema Validation 6.3.2. "minLength"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.2). #[serde(skip_serializing_if = "Option::is_none")] pub min_length: Option, + /// The `pattern` keyword. + /// + /// See [JSON Schema Validation 6.3.3. "pattern"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.3.3). #[serde(skip_serializing_if = "Option::is_none")] pub pattern: Option, } +/// Properties of a [`SchemaObject`] which define validation assertions for arrays. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)] #[serde(rename_all = "camelCase", default)] pub struct ArrayValidation { + /// The `items` keyword. + /// + /// See [JSON Schema 9.3.1.1. "items"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.1). #[serde(skip_serializing_if = "Option::is_none")] pub items: Option>, + /// The `additionalItems` keyword. + /// + /// See [JSON Schema 9.3.1.2. "additionalItems"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.2). #[serde(skip_serializing_if = "Option::is_none")] pub additional_items: Option>, + /// The `maxItems` keyword. + /// + /// See [JSON Schema Validation 6.4.1. "maxItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.1). #[serde(skip_serializing_if = "Option::is_none")] pub max_items: Option, + /// The `minItems` keyword. + /// + /// See [JSON Schema Validation 6.4.2. "minItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.2). #[serde(skip_serializing_if = "Option::is_none")] pub min_items: Option, + /// The `uniqueItems` keyword. + /// + /// See [JSON Schema Validation 6.4.3. "uniqueItems"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.4.3). #[serde(skip_serializing_if = "Option::is_none")] pub unique_items: Option, + /// The `contains` keyword. + /// + /// See [JSON Schema 9.3.1.4. "contains"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.1.4). #[serde(skip_serializing_if = "Option::is_none")] pub contains: Option>, } +/// Properties of a [`SchemaObject`] which define validation assertions for objects. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)] #[serde(rename_all = "camelCase", default)] pub struct ObjectValidation { + /// The `maxProperties` keyword. + /// + /// See [JSON Schema Validation 6.5.1. "maxProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.1). #[serde(skip_serializing_if = "Option::is_none")] pub max_properties: Option, + /// The `minProperties` keyword. + /// + /// See [JSON Schema Validation 6.5.2. "minProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.2). #[serde(skip_serializing_if = "Option::is_none")] pub min_properties: Option, + /// The `required` keyword. + /// + /// See [JSON Schema Validation 6.5.3. "required"](https://tools.ietf.org/html/draft-handrews-json-schema-validation-02#section-6.5.3). #[serde(skip_serializing_if = "Set::is_empty")] pub required: Set, + /// The `properties` keyword. + /// + /// See [JSON Schema 9.3.2.1. "properties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1). #[serde(skip_serializing_if = "Map::is_empty")] pub properties: Map, + /// The `patternProperties` keyword. + /// + /// See [JSON Schema 9.3.2.2. "patternProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.2). #[serde(skip_serializing_if = "Map::is_empty")] pub pattern_properties: Map, + /// The `additionalProperties` keyword. + /// + /// See [JSON Schema 9.3.2.3. "additionalProperties"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.3). #[serde(skip_serializing_if = "Option::is_none")] pub additional_properties: Option>, + /// The `propertyNames` keyword. + /// + /// See [JSON Schema 9.3.2.5. "propertyNames"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.5). #[serde(skip_serializing_if = "Option::is_none")] pub property_names: Option>, }