Skip to content

Commit

Permalink
Make schema_name() return Cow<'static, str> instead of String
Browse files Browse the repository at this point in the history
  • Loading branch information
GREsau committed May 26, 2024
1 parent fe05631 commit 1aaa162
Show file tree
Hide file tree
Showing 25 changed files with 126 additions and 157 deletions.
13 changes: 5 additions & 8 deletions docs/2-implementing.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ permalink: /implementing/
## schema_name

```rust
fn schema_name() -> String;
fn schema_name() -> Cow<'static, str>;
```

This function returns the human-readable friendly name of the type's schema, which frequently is just the name of the type itself. The schema name is used as the title for root schemas, and the key within the root's `definitions` property for subschemas.

NB in a future version of schemars, it's likely that this function will be changed to return a `Cow<'static, str>`.

## schema_id

```rust
Expand All @@ -29,8 +27,7 @@ This function returns a unique identifier of the type's schema - if two types re

```rust
fn schema_id() -> Cow<'static, str> {
Cow::Owned(
format!("[{}]", T::schema_id()))
format!("[{}]", T::schema_id()).into()
}
```

Expand All @@ -40,14 +37,14 @@ For a type with no generic type arguments, a reasonable implementation of this f

```rust
impl JsonSchema for NonGenericType {
fn schema_name() -> String {
fn schema_name() -> Cow<'static, str> {
// Exclude the module path to make the name in generated schemas clearer.
"NonGenericType".to_owned()
"NonGenericType".into()
}

fn schema_id() -> Cow<'static, str> {
// Include the module, in case a type with the same name is in another module/crate
Cow::Borrowed(concat!(module_path!(), "::NonGenericType"))
concat!(module_path!(), "::NonGenericType").into()
}

fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
Expand Down
35 changes: 17 additions & 18 deletions schemars/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ use crate::{visit::*, JsonSchema};
use dyn_clone::DynClone;
use serde::Serialize;
use serde_json::{Map, Value};
use std::borrow::Cow;
use std::collections::HashMap;
use std::{any::Any, collections::HashSet, fmt::Debug};

type CowStr = std::borrow::Cow<'static, str>;

/// Settings to customize how Schemas are generated.
///
/// The default settings currently conform to [JSON Schema 2020-12](https://json-schema.org/specification-links#2020-12), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
Expand Down Expand Up @@ -166,9 +167,9 @@ impl SchemaSettings {
pub struct SchemaGenerator {
settings: SchemaSettings,
definitions: Map<String, Value>,
pending_schema_ids: HashSet<Cow<'static, str>>,
schema_id_to_name: HashMap<Cow<'static, str>, String>,
used_schema_names: HashSet<String>,
pending_schema_ids: HashSet<CowStr>,
schema_id_to_name: HashMap<CowStr, CowStr>,
used_schema_names: HashSet<CowStr>,
}

impl Clone for SchemaGenerator {
Expand Down Expand Up @@ -230,11 +231,11 @@ impl SchemaGenerator {
Some(n) => n,
None => {
let base_name = T::schema_name();
let mut name = String::new();
let mut name = CowStr::Borrowed("");

if self.used_schema_names.contains(&base_name) {
if self.used_schema_names.contains(base_name.as_ref()) {
for i in 2.. {
name = format!("{}{}", base_name, i);
name = format!("{}{}", base_name, i).into();
if !self.used_schema_names.contains(&name) {
break;
}
Expand All @@ -250,7 +251,7 @@ impl SchemaGenerator {
};

let reference = format!("#{}/{}", self.definitions_path_stripped(), name);
if !self.definitions.contains_key(&name) {
if !self.definitions.contains_key(name.as_ref()) {
self.insert_new_subschema_for::<T>(name, id);
}
Schema::new_ref(reference)
Expand All @@ -259,18 +260,14 @@ impl SchemaGenerator {
}
}

fn insert_new_subschema_for<T: ?Sized + JsonSchema>(
&mut self,
name: String,
id: Cow<'static, str>,
) {
fn insert_new_subschema_for<T: ?Sized + JsonSchema>(&mut self, name: CowStr, id: CowStr) {
let dummy = false.into();
// insert into definitions BEFORE calling json_schema to avoid infinite recursion
self.definitions.insert(name.clone(), dummy);
self.definitions.insert(name.clone().into(), dummy);

let schema = self.json_schema_internal::<T>(id);

self.definitions.insert(name, schema.to_value());
self.definitions.insert(name.into(), schema.to_value());
}

/// Borrows the collection of all [referenceable](JsonSchema::is_referenceable) schemas that have been generated.
Expand Down Expand Up @@ -410,15 +407,15 @@ impl SchemaGenerator {
Ok(schema)
}

fn json_schema_internal<T: ?Sized + JsonSchema>(&mut self, id: Cow<'static, str>) -> Schema {
fn json_schema_internal<T: ?Sized + JsonSchema>(&mut self, id: CowStr) -> Schema {
struct PendingSchemaState<'a> {
gen: &'a mut SchemaGenerator,
id: Cow<'static, str>,
id: CowStr,
did_add: bool,
}

impl<'a> PendingSchemaState<'a> {
fn new(gen: &'a mut SchemaGenerator, id: Cow<'static, str>) -> Self {
fn new(gen: &'a mut SchemaGenerator, id: CowStr) -> Self {
let did_add = gen.pending_schema_ids.insert(id.clone());
Self { gen, id, did_add }
}
Expand Down Expand Up @@ -477,6 +474,8 @@ impl SchemaGenerator {
}
}

/// Returns `self.settings.definitions_path` as a plain JSON pointer to the definitions object,
/// i.e. without a leading '#' or trailing '/'
fn definitions_path_stripped(&self) -> &str {
let path = &self.settings.definitions_path;
let path = path.strip_prefix('#').unwrap_or(path);
Expand Down
13 changes: 6 additions & 7 deletions schemars/src/json_schema_impls/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use std::borrow::Cow;
impl<T> JsonSchema for [T; 0] {
no_ref_schema!();

fn schema_name() -> String {
"EmptyArray".to_owned()
fn schema_name() -> Cow<'static, str> {
"EmptyArray".into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("[]")
"[]".into()
}

fn json_schema(_: &mut SchemaGenerator) -> Schema {
Expand All @@ -28,13 +28,12 @@ macro_rules! array_impls {
impl<T: JsonSchema> JsonSchema for [T; $len] {
no_ref_schema!();

fn schema_name() -> String {
format!("Array_size_{}_of_{}", $len, T::schema_name())
fn schema_name() -> Cow<'static, str> {
format!("Array_size_{}_of_{}", $len, T::schema_name()).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Owned(
format!("[{}; {}]", $len, T::schema_id()))
format!("[{}; {}]", $len, T::schema_id()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
4 changes: 2 additions & 2 deletions schemars/src/json_schema_impls/arrayvec07.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ where
{
no_ref_schema!();

fn schema_name() -> String {
format!("Array_up_to_size_{}_of_{}", CAP, T::schema_name())
fn schema_name() -> std::borrow::Cow<'static, str> {
format!("Array_up_to_size_{}_of_{}", CAP, T::schema_name()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
12 changes: 6 additions & 6 deletions schemars/src/json_schema_impls/chrono04.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use std::borrow::Cow;
impl JsonSchema for Weekday {
no_ref_schema!();

fn schema_name() -> String {
"Weekday".to_owned()
fn schema_name() -> Cow<'static, str> {
"Weekday".into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("chrono::Weekday")
"chrono::Weekday".into()
}

fn json_schema(_: &mut SchemaGenerator) -> Schema {
Expand All @@ -38,12 +38,12 @@ macro_rules! formatted_string_impl {
impl $($desc)+ {
no_ref_schema!();

fn schema_name() -> String {
stringify!($ty).to_owned()
fn schema_name() -> Cow<'static, str> {
stringify!($ty).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Borrowed(stringify!(chrono::$ty))
stringify!(chrono::$ty).into()
}

fn json_schema(_: &mut SchemaGenerator) -> Schema {
Expand Down
24 changes: 12 additions & 12 deletions schemars/src/json_schema_impls/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use std::ops::{Bound, Range, RangeInclusive};
impl<T: JsonSchema> JsonSchema for Option<T> {
no_ref_schema!();

fn schema_name() -> String {
format!("Nullable_{}", T::schema_name())
fn schema_name() -> Cow<'static, str> {
format!("Nullable_{}", T::schema_name()).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Option<{}>", T::schema_id()))
format!("Option<{}>", T::schema_id()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down Expand Up @@ -69,12 +69,12 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
}

impl<T: JsonSchema, E: JsonSchema> JsonSchema for Result<T, E> {
fn schema_name() -> String {
format!("Result_of_{}_or_{}", T::schema_name(), E::schema_name())
fn schema_name() -> Cow<'static, str> {
format!("Result_of_{}_or_{}", T::schema_name(), E::schema_name()).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Result<{}, {}>", T::schema_id(), E::schema_id()))
format!("Result<{}, {}>", T::schema_id(), E::schema_id()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand All @@ -100,12 +100,12 @@ impl<T: JsonSchema, E: JsonSchema> JsonSchema for Result<T, E> {
}

impl<T: JsonSchema> JsonSchema for Bound<T> {
fn schema_name() -> String {
format!("Bound_of_{}", T::schema_name())
fn schema_name() -> Cow<'static, str> {
format!("Bound_of_{}", T::schema_name()).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Bound<{}>", T::schema_id()))
format!("Bound<{}>", T::schema_id()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down Expand Up @@ -135,12 +135,12 @@ impl<T: JsonSchema> JsonSchema for Bound<T> {
}

impl<T: JsonSchema> JsonSchema for Range<T> {
fn schema_name() -> String {
format!("Range_of_{}", T::schema_name())
fn schema_name() -> Cow<'static, str> {
format!("Range_of_{}", T::schema_name()).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Range<{}>", T::schema_id()))
format!("Range<{}>", T::schema_id()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
8 changes: 2 additions & 6 deletions schemars/src/json_schema_impls/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ macro_rules! decimal_impl {
impl JsonSchema for $type {
no_ref_schema!();

fn schema_name() -> String {
"Decimal".to_owned()
}

fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("Decimal")
fn schema_name() -> Cow<'static, str> {
"Decimal".into()
}

fn json_schema(_: &mut SchemaGenerator) -> Schema {
Expand Down
10 changes: 3 additions & 7 deletions schemars/src/json_schema_impls/either1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ use std::borrow::Cow;
impl<L: JsonSchema, R: JsonSchema> JsonSchema for Either<L, R> {
no_ref_schema!();

fn schema_name() -> String {
format!("Either_{}_or_{}", L::schema_name(), R::schema_name())
fn schema_name() -> Cow<'static, str> {
format!("Either_{}_or_{}", L::schema_name(), R::schema_name()).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!(
"either::Either<{}, {}>",
L::schema_id(),
R::schema_id()
))
format!("either::Either<{}, {}>", L::schema_id(), R::schema_id()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
6 changes: 3 additions & 3 deletions schemars/src/json_schema_impls/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use std::borrow::Cow;
use std::ffi::{CStr, CString, OsStr, OsString};

impl JsonSchema for OsString {
fn schema_name() -> String {
"OsString".to_owned()
fn schema_name() -> Cow<'static, str> {
"OsString".into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Borrowed("std::ffi::OsString")
"std::ffi::OsString".into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
6 changes: 3 additions & 3 deletions schemars/src/json_schema_impls/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ macro_rules! map_impl {
{
no_ref_schema!();

fn schema_name() -> String {
format!("Map_of_{}", V::schema_name())
fn schema_name() -> Cow<'static, str> {
format!("Map_of_{}", V::schema_name()).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Owned(format!("Map<{}>", V::schema_id()))
format!("Map<{}>", V::schema_id()).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
2 changes: 1 addition & 1 deletion schemars/src/json_schema_impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ macro_rules! forward_impl {
<$target>::is_referenceable()
}

fn schema_name() -> String {
fn schema_name() -> std::borrow::Cow<'static, str> {
<$target>::schema_name()
}

Expand Down
6 changes: 3 additions & 3 deletions schemars/src/json_schema_impls/nonzero_signed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ macro_rules! nonzero_unsigned_impl {
impl JsonSchema for $type {
no_ref_schema!();

fn schema_name() -> String {
stringify!($type).to_owned()
fn schema_name() -> Cow<'static, str> {
stringify!($type).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Borrowed(stringify!(std::num::$type))
stringify!(std::num::$type).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
8 changes: 4 additions & 4 deletions schemars/src/json_schema_impls/nonzero_unsigned.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::gen::SchemaGenerator;
use crate::Schema;
use crate::JsonSchema;
use crate::Schema;
use std::borrow::Cow;
use std::num::*;

Expand All @@ -9,12 +9,12 @@ macro_rules! nonzero_unsigned_impl {
impl JsonSchema for $type {
no_ref_schema!();

fn schema_name() -> String {
stringify!($type).to_owned()
fn schema_name() -> Cow<'static, str> {
stringify!($type).into()
}

fn schema_id() -> Cow<'static, str> {
Cow::Borrowed(stringify!(std::num::$type))
stringify!(std::num::$type).into()
}

fn json_schema(gen: &mut SchemaGenerator) -> Schema {
Expand Down
Loading

0 comments on commit 1aaa162

Please sign in to comment.