Skip to content

Commit 87d82b2

Browse files
authored
be more permissive of simple enum variants (#500)
1 parent 1f2d83f commit 87d82b2

File tree

3 files changed

+135
-3
lines changed

3 files changed

+135
-3
lines changed

typify-impl/src/enums.rs

+36-3
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ impl TypeSpace {
8989
// variant that we'd never use... I guess.
9090
Schema::Bool(false) => todo!(),
9191

92-
// Strings must be simple enumerations.
92+
// Strings must be simple enumerations or constants.
9393
Schema::Object(SchemaObject {
9494
metadata,
95-
instance_type: Some(SingleOrVec::Single(single)),
95+
instance_type,
9696
format: None,
9797
enum_values: Some(values),
9898
const_value: None,
@@ -103,7 +103,13 @@ impl TypeSpace {
103103
object: _,
104104
reference: None,
105105
extensions: _,
106-
}) if single.as_ref() == &InstanceType::String => {
106+
}) => {
107+
match instance_type {
108+
Some(SingleOrVec::Single(single))
109+
if single.as_ref() == &InstanceType::String => {}
110+
None => {}
111+
_ => return None,
112+
};
107113
// Confirm that all values are, in fact, simple strings.
108114
// Simple strings become simple variants. If any is not
109115
// a string, we'll end up returning None
@@ -117,6 +123,33 @@ impl TypeSpace {
117123
})
118124
.collect()
119125
}
126+
Schema::Object(SchemaObject {
127+
metadata,
128+
instance_type,
129+
format: None,
130+
enum_values: None,
131+
const_value: Some(value),
132+
subschemas: None,
133+
number: _,
134+
string: _,
135+
array: _,
136+
object: _,
137+
reference: None,
138+
extensions: _,
139+
}) => {
140+
match instance_type {
141+
Some(SingleOrVec::Single(single))
142+
if single.as_ref() == &InstanceType::String => {}
143+
None => {}
144+
_ => return None,
145+
};
146+
std::iter::once(value.as_str().map(|variant_name| ProtoVariant::Simple {
147+
name: variant_name,
148+
description: metadata_description(metadata),
149+
}))
150+
.collect()
151+
}
152+
120153
other => match get_object(other) {
121154
// Objects must have a single property, and that
122155
// property must be required. The type of that lone

typify/tests/schemas/various-enums.json

+20
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,26 @@
258258
}
259259
}
260260
]
261+
},
262+
"commented-variants": {
263+
"oneOf": [
264+
{
265+
"enum": [
266+
"A"
267+
],
268+
"description": "An A"
269+
},
270+
{
271+
"enum": [
272+
"B"
273+
],
274+
"description": "A B"
275+
},
276+
{
277+
"const": "C",
278+
"description": "a pirate's favorite letter"
279+
}
280+
]
261281
}
262282
}
263283
}

typify/tests/schemas/various-enums.rs

+79
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,85 @@ impl Default for AlternativeEnum {
9696
AlternativeEnum::Choice2
9797
}
9898
}
99+
#[doc = "CommentedVariants"]
100+
#[doc = r""]
101+
#[doc = r" <details><summary>JSON schema</summary>"]
102+
#[doc = r""]
103+
#[doc = r" ```json"]
104+
#[doc = "{"]
105+
#[doc = " \"oneOf\": ["]
106+
#[doc = " {"]
107+
#[doc = " \"description\": \"An A\","]
108+
#[doc = " \"enum\": ["]
109+
#[doc = " \"A\""]
110+
#[doc = " ]"]
111+
#[doc = " },"]
112+
#[doc = " {"]
113+
#[doc = " \"description\": \"A B\","]
114+
#[doc = " \"enum\": ["]
115+
#[doc = " \"B\""]
116+
#[doc = " ]"]
117+
#[doc = " },"]
118+
#[doc = " {"]
119+
#[doc = " \"description\": \"a pirate's favorite letter\","]
120+
#[doc = " \"const\": \"C\""]
121+
#[doc = " }"]
122+
#[doc = " ]"]
123+
#[doc = "}"]
124+
#[doc = r" ```"]
125+
#[doc = r" </details>"]
126+
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
127+
pub enum CommentedVariants {
128+
#[doc = "An A"]
129+
A,
130+
#[doc = "A B"]
131+
B,
132+
#[doc = "a pirate's favorite letter"]
133+
C,
134+
}
135+
impl From<&CommentedVariants> for CommentedVariants {
136+
fn from(value: &CommentedVariants) -> Self {
137+
value.clone()
138+
}
139+
}
140+
impl ToString for CommentedVariants {
141+
fn to_string(&self) -> String {
142+
match *self {
143+
Self::A => "A".to_string(),
144+
Self::B => "B".to_string(),
145+
Self::C => "C".to_string(),
146+
}
147+
}
148+
}
149+
impl std::str::FromStr for CommentedVariants {
150+
type Err = self::error::ConversionError;
151+
fn from_str(value: &str) -> Result<Self, self::error::ConversionError> {
152+
match value {
153+
"A" => Ok(Self::A),
154+
"B" => Ok(Self::B),
155+
"C" => Ok(Self::C),
156+
_ => Err("invalid value".into()),
157+
}
158+
}
159+
}
160+
impl std::convert::TryFrom<&str> for CommentedVariants {
161+
type Error = self::error::ConversionError;
162+
fn try_from(value: &str) -> Result<Self, self::error::ConversionError> {
163+
value.parse()
164+
}
165+
}
166+
impl std::convert::TryFrom<&String> for CommentedVariants {
167+
type Error = self::error::ConversionError;
168+
fn try_from(value: &String) -> Result<Self, self::error::ConversionError> {
169+
value.parse()
170+
}
171+
}
172+
impl std::convert::TryFrom<String> for CommentedVariants {
173+
type Error = self::error::ConversionError;
174+
fn try_from(value: String) -> Result<Self, self::error::ConversionError> {
175+
value.parse()
176+
}
177+
}
99178
#[doc = "DiskAttachment"]
100179
#[doc = r""]
101180
#[doc = r" <details><summary>JSON schema</summary>"]

0 commit comments

Comments
 (0)