Skip to content

Commit e446496

Browse files
committed
re-order untagged enum
Signed-off-by: Farès Chati <fchati@smartandconnective.com>
1 parent 11fc5f7 commit e446496

File tree

3 files changed

+81
-17
lines changed

3 files changed

+81
-17
lines changed

typify-impl/src/convert.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use schemars::schema::{
1616

1717
use crate::util::get_type_name;
1818

19-
use crate::{Error, Name, Result, TypeSpace, TypeSpaceImpl};
19+
use crate::{Error, Name, ReorderedInstanceType, Result, TypeSpace, TypeSpaceImpl};
2020

2121
pub const STD_NUM_NONZERO_PREFIX: &str = "::std::num::NonZero";
2222

@@ -672,7 +672,13 @@ impl TypeSpace {
672672
} => {
673673
// Eliminate duplicates (they hold no significance); they
674674
// aren't supposed to be there, but we can still handle it.
675-
let unique_types = instance_types.iter().collect::<BTreeSet<_>>();
675+
// Convert the types into a form that puts integers before numbers to ensure that
676+
// integer get matched before numbers in untagged enum generation.
677+
let unique_types = instance_types
678+
.iter()
679+
.copied()
680+
.map(Into::into)
681+
.collect::<BTreeSet<ReorderedInstanceType>>();
676682

677683
// Massage the data into labeled subschemas with the following
678684
// format:
@@ -695,8 +701,9 @@ impl TypeSpace {
695701
// but why do tomorrow what we could easily to today?
696702
let subschemas = unique_types
697703
.into_iter()
704+
.map(InstanceType::from)
698705
.map(|it| {
699-
let instance_type = Some(SingleOrVec::Single(Box::new(*it)));
706+
let instance_type = Some(SingleOrVec::Single(Box::new(it)));
700707
let (label, inner_schema) = match it {
701708
InstanceType::Null => (
702709
"null",

typify-impl/src/lib.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use log::{debug, info};
1111
use output::OutputSpace;
1212
use proc_macro2::TokenStream;
1313
use quote::{format_ident, quote, ToTokens};
14-
use schemars::schema::{Metadata, RootSchema, Schema};
14+
use schemars::schema::{InstanceType, Metadata, RootSchema, Schema};
1515
use thiserror::Error;
1616
use type_entry::{
1717
StructPropertyState, TypeEntry, TypeEntryDetails, TypeEntryNative, TypeEntryNewtype,
@@ -1212,6 +1212,63 @@ impl TypeNewtype<'_> {
12121212
}
12131213
}
12141214

1215+
/// A re-ordering of JSON schema instance types that puts integer values before
1216+
/// number values.
1217+
///
1218+
/// This is used for untagged enum generation to ensure that integer values
1219+
/// are matched before number values.
1220+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1221+
pub enum ReorderedInstanceType {
1222+
/// The JSON schema instance type `null`.
1223+
Null,
1224+
1225+
/// The JSON schema instance type `boolean`.
1226+
Boolean,
1227+
1228+
/// The JSON schema instance type `integer`.
1229+
Integer,
1230+
1231+
/// The JSON schema instance type `number`.
1232+
Number,
1233+
1234+
/// The JSON schema instance type `string`.
1235+
String,
1236+
1237+
/// The JSON schema instance type `array`.
1238+
Array,
1239+
1240+
/// The JSON schema instance type `object`.
1241+
Object,
1242+
}
1243+
1244+
impl From<InstanceType> for ReorderedInstanceType {
1245+
fn from(instance_type: InstanceType) -> Self {
1246+
match instance_type {
1247+
InstanceType::Null => Self::Null,
1248+
InstanceType::Boolean => Self::Boolean,
1249+
InstanceType::Object => Self::Object,
1250+
InstanceType::Array => Self::Array,
1251+
InstanceType::Integer => Self::Integer,
1252+
InstanceType::Number => Self::Number,
1253+
InstanceType::String => Self::String,
1254+
}
1255+
}
1256+
}
1257+
1258+
impl From<ReorderedInstanceType> for InstanceType {
1259+
fn from(instance_type: ReorderedInstanceType) -> Self {
1260+
match instance_type {
1261+
ReorderedInstanceType::Null => Self::Null,
1262+
ReorderedInstanceType::Boolean => Self::Boolean,
1263+
ReorderedInstanceType::Object => Self::Object,
1264+
ReorderedInstanceType::Array => Self::Array,
1265+
ReorderedInstanceType::Integer => Self::Integer,
1266+
ReorderedInstanceType::Number => Self::Number,
1267+
ReorderedInstanceType::String => Self::String,
1268+
}
1269+
}
1270+
}
1271+
12151272
#[cfg(test)]
12161273
mod tests {
12171274
use schema::Schema;

typify/tests/schemas/multiple-instance-types.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ pub mod error {
4141
#[derive(:: serde :: Deserialize, :: serde :: Serialize, Clone, Debug)]
4242
#[serde(untagged)]
4343
pub enum IntOrStr {
44-
String(::std::string::String),
4544
Integer(i64),
45+
String(::std::string::String),
4646
}
4747
impl ::std::fmt::Display for IntOrStr {
4848
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
4949
match self {
50-
Self::String(x) => x.fmt(f),
5150
Self::Integer(x) => x.fmt(f),
51+
Self::String(x) => x.fmt(f),
5252
}
5353
}
5454
}
@@ -79,31 +79,31 @@ impl ::std::convert::From<i64> for IntOrStr {
7979
pub enum OneOfSeveral {
8080
Null,
8181
Boolean(bool),
82-
Object(::serde_json::Map<::std::string::String, ::serde_json::Value>),
83-
Array(::std::vec::Vec<::serde_json::Value>),
84-
String(::std::string::String),
8582
Integer(i64),
83+
String(::std::string::String),
84+
Array(::std::vec::Vec<::serde_json::Value>),
85+
Object(::serde_json::Map<::std::string::String, ::serde_json::Value>),
8686
}
8787
impl ::std::convert::From<bool> for OneOfSeveral {
8888
fn from(value: bool) -> Self {
8989
Self::Boolean(value)
9090
}
9191
}
92-
impl ::std::convert::From<::serde_json::Map<::std::string::String, ::serde_json::Value>>
93-
for OneOfSeveral
94-
{
95-
fn from(value: ::serde_json::Map<::std::string::String, ::serde_json::Value>) -> Self {
96-
Self::Object(value)
92+
impl ::std::convert::From<i64> for OneOfSeveral {
93+
fn from(value: i64) -> Self {
94+
Self::Integer(value)
9795
}
9896
}
9997
impl ::std::convert::From<::std::vec::Vec<::serde_json::Value>> for OneOfSeveral {
10098
fn from(value: ::std::vec::Vec<::serde_json::Value>) -> Self {
10199
Self::Array(value)
102100
}
103101
}
104-
impl ::std::convert::From<i64> for OneOfSeveral {
105-
fn from(value: i64) -> Self {
106-
Self::Integer(value)
102+
impl ::std::convert::From<::serde_json::Map<::std::string::String, ::serde_json::Value>>
103+
for OneOfSeveral
104+
{
105+
fn from(value: ::serde_json::Map<::std::string::String, ::serde_json::Value>) -> Self {
106+
Self::Object(value)
107107
}
108108
}
109109
#[doc = "`ReallyJustNull`"]

0 commit comments

Comments
 (0)