Remove various 'static bounds
Currently using an unreliable hack - assuming type name is unique D:
This commit is contained in:
parent
4f9956631e
commit
21a29dc6b5
3 changed files with 31 additions and 16 deletions
|
@ -1,6 +1,5 @@
|
||||||
use crate::make_schema::MakeSchema;
|
use crate::make_schema::{MakeSchema, SchemaTypeId};
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use core::any::TypeId;
|
|
||||||
use std::collections::BTreeMap as Map;
|
use std::collections::BTreeMap as Map;
|
||||||
use std::collections::BTreeSet as Set;
|
use std::collections::BTreeSet as Set;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
@ -8,7 +7,7 @@ use std::iter::FromIterator;
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct SchemaGenerator {
|
pub struct SchemaGenerator {
|
||||||
names: Set<String>,
|
names: Set<String>,
|
||||||
definitions: Map<TypeId, (String, Schema)>,
|
definitions: Map<SchemaTypeId, (String, Schema)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SchemaGenerator {
|
impl SchemaGenerator {
|
||||||
|
@ -18,23 +17,24 @@ impl SchemaGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subschema_for<T: MakeSchema + 'static>(&mut self) -> Schema {
|
pub fn subschema_for<T: ?Sized + MakeSchema>(&mut self) -> Schema {
|
||||||
if !T::generates_ref_schema() {
|
if !T::generates_ref_schema() {
|
||||||
return T::make_schema(self);
|
return T::make_schema(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
let type_id = TypeId::of::<T>();
|
let type_id = T::schema_type_id();
|
||||||
// TODO is there a nicer way to do this?
|
// TODO is there a nicer way to do this?
|
||||||
if !self.definitions.contains_key(&type_id) {
|
if !self.definitions.contains_key(&type_id) {
|
||||||
let name = self.make_unique_name::<T>();
|
let name = self.make_unique_name::<T>();
|
||||||
self.names.insert(name.clone());
|
self.names.insert(name.clone());
|
||||||
// insert into definitions BEFORE calling make_schema to avoid infinite recursion
|
// insert into definitions BEFORE calling make_schema to avoid infinite recursion
|
||||||
let dummy = Schema::Bool(false);
|
let dummy = Schema::Bool(false);
|
||||||
self.definitions.insert(type_id, (name.clone(), dummy));
|
self.definitions
|
||||||
|
.insert(type_id.clone(), (name.clone(), dummy));
|
||||||
|
|
||||||
let schema = T::make_schema(self);
|
let schema = T::make_schema(self);
|
||||||
self.definitions
|
self.definitions
|
||||||
.entry(type_id)
|
.entry(type_id.clone())
|
||||||
.and_modify(|(_, s)| *s = schema);
|
.and_modify(|(_, s)| *s = schema);
|
||||||
}
|
}
|
||||||
let ref name = self.definitions.get(&type_id).unwrap().0;
|
let ref name = self.definitions.get(&type_id).unwrap().0;
|
||||||
|
@ -52,7 +52,7 @@ impl SchemaGenerator {
|
||||||
Map::from_iter(self.definitions.into_iter().map(|(_, v)| v))
|
Map::from_iter(self.definitions.into_iter().map(|(_, v)| v))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_schema_for<T: MakeSchema>(&mut self) -> Schema {
|
pub fn root_schema_for<T: ?Sized + MakeSchema>(&mut self) -> Schema {
|
||||||
let schema = T::make_schema(self);
|
let schema = T::make_schema(self);
|
||||||
if let Schema::Object(mut o) = schema {
|
if let Schema::Object(mut o) = schema {
|
||||||
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
||||||
|
@ -63,7 +63,7 @@ impl SchemaGenerator {
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_root_schema_for<T: MakeSchema>(mut self) -> Schema {
|
pub fn into_root_schema_for<T: ?Sized + MakeSchema>(mut self) -> Schema {
|
||||||
let schema = T::make_schema(&mut self);
|
let schema = T::make_schema(&mut self);
|
||||||
if let Schema::Object(mut o) = schema {
|
if let Schema::Object(mut o) = schema {
|
||||||
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
||||||
|
@ -74,7 +74,7 @@ impl SchemaGenerator {
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_unique_name<T: MakeSchema>(&mut self) -> String {
|
fn make_unique_name<T: ?Sized + MakeSchema>(&mut self) -> String {
|
||||||
let base_name = T::schema_name();
|
let base_name = T::schema_name();
|
||||||
// TODO remove namespace, remove special chars
|
// TODO remove namespace, remove special chars
|
||||||
if self.names.contains(&base_name) {
|
if self.names.contains(&base_name) {
|
||||||
|
|
|
@ -35,7 +35,8 @@ struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let schema = <&str>::make_schema();
|
let gen = generator::SchemaGenerator::new();
|
||||||
|
let schema = gen.into_root_schema_for::<str>();
|
||||||
let json = serde_json::to_string(&schema)?;
|
let json = serde_json::to_string(&schema)?;
|
||||||
println!("{}", json);
|
println!("{}", json);
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,26 @@ use crate::schema::*;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::collections::BTreeMap as Map;
|
use std::collections::BTreeMap as Map;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||||
|
pub struct SchemaTypeId(&'static str);
|
||||||
|
|
||||||
pub trait MakeSchema {
|
pub trait MakeSchema {
|
||||||
|
fn schema_type_id() -> SchemaTypeId {
|
||||||
|
// FIXME schema name might not be unique!
|
||||||
|
SchemaTypeId(core::any::type_name::<Self>())
|
||||||
|
}
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
|
// TODO this requires nightly
|
||||||
|
// It's probably worth removing the default implemenation,
|
||||||
|
// then make every impl in this file set an explicit name
|
||||||
|
// Or maybe hide it under feature flag?
|
||||||
core::any::type_name::<Self>().to_owned()
|
core::any::type_name::<Self>().to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generates_ref_schema() -> bool {
|
fn generates_ref_schema() -> bool {
|
||||||
|
// TODO default this to true as it's safer
|
||||||
|
// But this would mean every impl in this file needs to override it :(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +107,7 @@ impl<T> MakeSchema for [T; 0] {
|
||||||
macro_rules! array_impls {
|
macro_rules! array_impls {
|
||||||
($($len:tt)+) => {
|
($($len:tt)+) => {
|
||||||
$(
|
$(
|
||||||
impl<T: MakeSchema + 'static> MakeSchema for [T; $len]
|
impl<T: MakeSchema> MakeSchema for [T; $len]
|
||||||
{
|
{
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
let mut extra_properties = Map::new();
|
let mut extra_properties = Map::new();
|
||||||
|
@ -124,7 +138,7 @@ macro_rules! seq_impl {
|
||||||
($($desc:tt)+) => {
|
($($desc:tt)+) => {
|
||||||
impl $($desc)+
|
impl $($desc)+
|
||||||
where
|
where
|
||||||
T: MakeSchema + 'static,
|
T: MakeSchema,
|
||||||
{
|
{
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema
|
fn make_schema(gen: &mut SchemaGenerator) -> Schema
|
||||||
{
|
{
|
||||||
|
@ -152,7 +166,7 @@ macro_rules! map_impl {
|
||||||
impl $($desc)+
|
impl $($desc)+
|
||||||
where
|
where
|
||||||
K: Into<String>,
|
K: Into<String>,
|
||||||
T: MakeSchema + 'static,
|
T: MakeSchema,
|
||||||
{
|
{
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema
|
fn make_schema(gen: &mut SchemaGenerator) -> Schema
|
||||||
{
|
{
|
||||||
|
@ -176,7 +190,7 @@ map_impl!(<K, T: Eq + core::hash::Hash, H: core::hash::BuildHasher> MakeSchema f
|
||||||
|
|
||||||
////////// OPTION //////////
|
////////// OPTION //////////
|
||||||
|
|
||||||
impl<T: MakeSchema + 'static> MakeSchema for Option<T> {
|
impl<T: MakeSchema> MakeSchema for Option<T> {
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
match gen.subschema_for::<T>() {
|
match gen.subschema_for::<T>() {
|
||||||
Schema::Bool(true) => true.into(),
|
Schema::Bool(true) => true.into(),
|
||||||
|
@ -196,7 +210,7 @@ macro_rules! deref_impl {
|
||||||
($($desc:tt)+) => {
|
($($desc:tt)+) => {
|
||||||
impl $($desc)+
|
impl $($desc)+
|
||||||
where
|
where
|
||||||
T: MakeSchema + 'static,
|
T: MakeSchema,
|
||||||
{
|
{
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
gen.subschema_for::<T>()
|
gen.subschema_for::<T>()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue