Skip to content

Commit

Permalink
Replace is_referenceable() with always_inline_schema()
Browse files Browse the repository at this point in the history
  • Loading branch information
GREsau committed May 26, 2024
1 parent 1aaa162 commit f8b56cb
Show file tree
Hide file tree
Showing 22 changed files with 53 additions and 52 deletions.
10 changes: 5 additions & 5 deletions docs/2-implementing.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ This function creates the JSON schema itself. The `gen` argument can be used to

`json_schema` should not return a `$ref` schema.

## is_referenceable (optional)
## always_inline_schema (optional)

```rust
fn is_referenceable() -> bool;
fn always_inline_schema() -> bool;
```

If this function returns `true`, then Schemars can re-use the generate schema where possible by adding it to the root schema's `definitions` and having other schemas reference it using the `$ref` keyword. This can greatly simplify schemas that include a particular type multiple times, especially if that type's schema is fairly complex.
If this function returns `false`, then Schemars can re-use the generate schema where possible by adding it to the root schema's `definitions` and having other schemas reference it using the `$ref` keyword. This can greatly simplify schemas that include a particular type multiple times, especially if that type's schema is fairly complex.

Generally, this should return `false` for types with simple schemas (such as primitives). For more complex types, it should return `true`. For recursive types, this **must** return `true` to prevent infinite cycles when generating schemas.
Generally, this should return `true` for types with simple schemas (such as primitives). For more complex types, it should return `false`. For recursive types, this **must** return `false` to prevent infinite cycles when generating schemas.

The default implementation of this function returns `true` to reduce the chance of someone inadvertently causing infinite cycles with recursive types.
The default implementation of this function returns `false` to reduce the chance of someone inadvertently causing infinite cycles with recursive types.
16 changes: 8 additions & 8 deletions schemars/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,14 @@ impl SchemaGenerator {

/// Generates a JSON Schema for the type `T`, and returns either the schema itself or a `$ref` schema referencing `T`'s schema.
///
/// If `T` is [referenceable](JsonSchema::is_referenceable), this will add `T`'s schema to this generator's definitions, and
/// If `T` is not [inlined](JsonSchema::always_inline_schema), this will add `T`'s schema to this generator's definitions, and
/// return a `$ref` schema referencing that schema. Otherwise, this method behaves identically to [`JsonSchema::json_schema`].
///
/// If `T`'s schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will
/// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
/// add them to the `SchemaGenerator`'s schema definitions.
pub fn subschema_for<T: ?Sized + JsonSchema>(&mut self) -> Schema {
let id = T::schema_id();
let return_ref = T::is_referenceable()
let return_ref = !T::always_inline_schema()
&& (!self.settings.inline_subschemas || self.pending_schema_ids.contains(&id));

if return_ref {
Expand Down Expand Up @@ -270,23 +270,23 @@ impl SchemaGenerator {
self.definitions.insert(name.into(), schema.to_value());
}

/// Borrows the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated.
/// Borrows the collection of all [non-inlined](JsonSchema::always_inline_schema) 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.
pub fn definitions(&self) -> &Map<String, Value> {
&self.definitions
}

/// Mutably borrows the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated.
/// Mutably borrows the collection of all [non-inlined](JsonSchema::always_inline_schema) 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.
pub fn definitions_mut(&mut self) -> &mut Map<String, Value> {
&mut self.definitions
}

/// Returns the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated,
/// Returns the collection of all [non-inlined](JsonSchema::always_inline_schema) schemas that have been generated,
/// leaving an empty map in its place.
///
/// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
Expand All @@ -302,7 +302,7 @@ impl SchemaGenerator {

/// 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
/// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) 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<T: ?Sized + JsonSchema>(&mut self) -> Schema {
Expand All @@ -326,7 +326,7 @@ impl SchemaGenerator {

/// 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
/// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) 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<T: ?Sized + JsonSchema>(mut self) -> Schema {
let mut schema = self.json_schema_internal::<T>(T::schema_id());
Expand Down
4 changes: 2 additions & 2 deletions schemars/src/json_schema_impls/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::borrow::Cow;

// Does not require T: JsonSchema.
impl<T> JsonSchema for [T; 0] {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"EmptyArray".into()
Expand All @@ -26,7 +26,7 @@ macro_rules! array_impls {
($($len:tt)+) => {
$(
impl<T: JsonSchema> JsonSchema for [T; $len] {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
format!("Array_size_{}_of_{}", $len, T::schema_name()).into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/arrayvec07.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ impl<T, const CAP: usize> JsonSchema for ArrayVec<T, CAP>
where
T: JsonSchema,
{
no_ref_schema!();
always_inline!();

fn schema_name() -> std::borrow::Cow<'static, str> {
format!("Array_up_to_size_{}_of_{}", CAP, T::schema_name()).into()
Expand Down
4 changes: 2 additions & 2 deletions schemars/src/json_schema_impls/chrono04.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use chrono04::prelude::*;
use std::borrow::Cow;

impl JsonSchema for Weekday {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"Weekday".into()
Expand Down Expand Up @@ -36,7 +36,7 @@ macro_rules! formatted_string_impl {
};
($ty:ident, $format:literal, $($desc:tt)+) => {
impl $($desc)+ {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
stringify!($ty).into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::borrow::Cow;
use std::ops::{Bound, Range, RangeInclusive};

impl<T: JsonSchema> JsonSchema for Option<T> {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
format!("Nullable_{}", T::schema_name()).into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::borrow::Cow;
macro_rules! decimal_impl {
($type:ty) => {
impl JsonSchema for $type {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"Decimal".into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/either1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use either1::Either;
use std::borrow::Cow;

impl<L: JsonSchema, R: JsonSchema> JsonSchema for Either<L, R> {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
format!("Either_{}_or_{}", L::schema_name(), R::schema_name()).into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ macro_rules! map_impl {
where
V: JsonSchema,
{
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
format!("Map_of_{}", V::schema_name()).into()
Expand Down
10 changes: 5 additions & 5 deletions schemars/src/json_schema_impls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
macro_rules! no_ref_schema {
macro_rules! always_inline {
() => {
fn is_referenceable() -> bool {
false
fn always_inline_schema() -> bool {
true
}
};
}

macro_rules! forward_impl {
(($($impl:tt)+) => $target:ty) => {
impl $($impl)+ {
fn is_referenceable() -> bool {
<$target>::is_referenceable()
fn always_inline_schema() -> bool {
<$target>::always_inline_schema()
}

fn schema_name() -> std::borrow::Cow<'static, str> {
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/nonzero_signed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::num::*;
macro_rules! nonzero_unsigned_impl {
($type:ty => $primitive:ty) => {
impl JsonSchema for $type {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
stringify!($type).into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/nonzero_unsigned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::num::*;
macro_rules! nonzero_unsigned_impl {
($type:ty => $primitive:ty) => {
impl JsonSchema for $type {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
stringify!($type).into()
Expand Down
8 changes: 4 additions & 4 deletions schemars/src/json_schema_impls/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
macro_rules! simple_impl {
($type:ty => $instance_type:literal) => {
impl JsonSchema for $type {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
$instance_type.into()
Expand All @@ -22,7 +22,7 @@ macro_rules! simple_impl {
};
($type:ty => $instance_type:literal, $format:literal) => {
impl JsonSchema for $type {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
$format.into()
Expand Down Expand Up @@ -65,7 +65,7 @@ simple_impl!(SocketAddrV6 => "string");
macro_rules! unsigned_impl {
($type:ty => $instance_type:literal, $format:literal) => {
impl JsonSchema for $type {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
$format.into()
Expand All @@ -90,7 +90,7 @@ unsigned_impl!(u128 => "integer", "uint128");
unsigned_impl!(usize => "integer", "uint");

impl JsonSchema for char {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"Character".into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/semver1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use semver1::Version;
use std::borrow::Cow;

impl JsonSchema for Version {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"Version".into()
Expand Down
4 changes: 2 additions & 2 deletions schemars/src/json_schema_impls/sequences.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ macro_rules! seq_impl {
where
T: JsonSchema,
{
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
format!("Array_of_{}", T::schema_name()).into()
Expand All @@ -34,7 +34,7 @@ macro_rules! set_impl {
where
T: JsonSchema,
{
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
format!("Set_of_{}", T::schema_name()).into()
Expand Down
4 changes: 2 additions & 2 deletions schemars/src/json_schema_impls/serdejson.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::borrow::Cow;
use std::collections::BTreeMap;

impl JsonSchema for Value {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"AnyValue".into()
Expand All @@ -19,7 +19,7 @@ impl JsonSchema for Value {
forward_impl!(Map<String, Value> => BTreeMap<String, Value>);

impl JsonSchema for Number {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"Number".into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ macro_rules! tuple_impls {
($($len:expr => ($($name:ident)+))+) => {
$(
impl<$($name: JsonSchema),+> JsonSchema for ($($name,)+) {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
let mut name = "Tuple_of_".to_owned();
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/url2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::borrow::Cow;
use url2::Url;

impl JsonSchema for Url {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"Url".into()
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/uuid1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::borrow::Cow;
use uuid1::Uuid;

impl JsonSchema for Uuid {
no_ref_schema!();
always_inline!();

fn schema_name() -> Cow<'static, str> {
"Uuid".into()
Expand Down
15 changes: 8 additions & 7 deletions schemars/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,15 @@ pub use schema::Schema;
///
pub trait JsonSchema {
/// Whether JSON Schemas generated for this type should be re-used where possible using the `$ref` keyword.
/// Whether JSON Schemas generated for this type should be included directly in parent schemas, rather than being
/// re-used where possible using the `$ref` keyword.
///
/// For trivial types (such as primitives), this should return `false`. For more complex types, it should return `true`.
/// For recursive types, this **must** return `true` to prevent infinite cycles when generating schemas.
/// For trivial types (such as primitives), this should return `true`. For more complex types, it should return `false`.
/// For recursive types, this **must** return `false` to prevent infinite cycles when generating schemas.
///
/// By default, this returns `true`.
fn is_referenceable() -> bool {
true
/// By default, this returns `false`.
fn always_inline_schema() -> bool {
false
}

/// The name of the generated JSON Schema.
Expand All @@ -132,7 +133,7 @@ pub trait JsonSchema {

/// Generates a JSON Schema for this type.
///
/// If the returned schema depends on any [referenceable](JsonSchema::is_referenceable) schemas, then this method will
/// If the returned schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
/// add them to the [`SchemaGenerator`](gen::SchemaGenerator)'s schema definitions.
///
/// This should not return a `$ref` schema.
Expand Down
4 changes: 2 additions & 2 deletions schemars_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To

#[automatically_derived]
impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause {
fn is_referenceable() -> bool {
<#ty as schemars::JsonSchema>::is_referenceable()
fn always_inline_schema() -> bool {
<#ty as schemars::JsonSchema>::always_inline_schema()
}

fn schema_name() -> std::borrow::Cow<'static, str> {
Expand Down
4 changes: 2 additions & 2 deletions schemars_derive/src/schema_exprs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ fn type_for_schema(with_attr: &WithAttr) -> (syn::Type, Option<TokenStream>) {
struct #ty_name;

impl schemars::JsonSchema for #ty_name {
fn is_referenceable() -> bool {
false
fn always_inline_schema() -> bool {
true
}

fn schema_name() -> std::borrow::Cow<'static, str> {
Expand Down

0 comments on commit f8b56cb

Please sign in to comment.