Skip to content

Commit 756af9f

Browse files
committed
Add support for enum hints
1 parent 21e489f commit 756af9f

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

src/lib.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
11
mod hint_set;
22

33
pub use hint_set::HintSet;
4+
use std::collections::HashSet;
45

56
#[derive(Debug)]
67
pub struct Hints<'a> {
8+
enums: HintSet<'a>,
79
values: HintSet<'a>,
810
discriminator: HintSet<'a>,
911
}
1012

1113
impl<'a> Hints<'a> {
12-
pub fn new(values: HintSet<'a>, discriminator: HintSet<'a>) -> Self {
14+
pub fn new(enums: HintSet<'a>, values: HintSet<'a>, discriminator: HintSet<'a>) -> Self {
1315
Hints {
16+
enums,
1417
values,
1518
discriminator,
1619
}
1720
}
1821

1922
fn sub_hints(&self, key: &str) -> Self {
2023
Self::new(
24+
self.enums.sub_hints(key),
2125
self.values.sub_hints(key),
2226
self.discriminator.sub_hints(key),
2327
)
2428
}
2529

30+
fn is_enum_active(&self) -> bool {
31+
self.enums.is_active()
32+
}
33+
2634
fn is_values_active(&self) -> bool {
2735
self.values.is_active()
2836
}
@@ -52,6 +60,7 @@ pub enum InferredSchema {
5260
Float64,
5361
String,
5462
Timestamp,
63+
Enum(HashSet<String>),
5564
Array(Box<InferredSchema>),
5665
Properties {
5766
required: HashMap<String, InferredSchema>,
@@ -85,7 +94,12 @@ impl InferredSchema {
8594
(InferredSchema::Unknown, Value::Bool(_)) => InferredSchema::Bool,
8695
(InferredSchema::Unknown, Value::Number(n)) => minimum_number_type(n),
8796
(InferredSchema::Unknown, Value::String(s)) => {
88-
if DateTime::parse_from_rfc3339(&s).is_ok() {
97+
if hints.is_enum_active() {
98+
let mut values = HashSet::new();
99+
values.insert(s);
100+
101+
InferredSchema::Enum(values)
102+
} else if DateTime::parse_from_rfc3339(&s).is_ok() {
89103
InferredSchema::Timestamp
90104
} else {
91105
InferredSchema::String
@@ -113,8 +127,6 @@ impl InferredSchema {
113127
if let Some(Value::String(mapping_key)) = obj.remove(discriminator) {
114128
let infer_rest = InferredSchema::Unknown.infer(Value::Object(obj), hints);
115129

116-
dbg!("infer rest", &discriminator, &infer_rest);
117-
118130
let mut mapping = HashMap::new();
119131
mapping.insert(mapping_key.to_owned(), infer_rest);
120132

@@ -193,6 +205,11 @@ impl InferredSchema {
193205
(InferredSchema::Timestamp, _) => InferredSchema::Any,
194206
(InferredSchema::String, Value::String(_)) => InferredSchema::String,
195207
(InferredSchema::String, _) => InferredSchema::Any,
208+
(InferredSchema::Enum(mut values), Value::String(s)) => {
209+
values.insert(s);
210+
InferredSchema::Enum(values)
211+
}
212+
(InferredSchema::Enum(_), _) => InferredSchema::Any,
196213
(InferredSchema::Array(prior), Value::Array(vals)) => {
197214
let mut sub_infer = *prior;
198215
for (i, v) in vals.into_iter().enumerate() {
@@ -320,6 +337,10 @@ impl InferredSchema {
320337
nullable: false,
321338
type_value: TypeValue::Timestamp,
322339
}),
340+
InferredSchema::Enum(values) => Form::Enum(form::Enum {
341+
nullable: false,
342+
values,
343+
}),
323344
InferredSchema::Array(sub_infer) => Form::Elements(form::Elements {
324345
nullable: false,
325346
schema: Box::new(sub_infer.into_schema()),

src/main.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clap::{App, AppSettings, Arg};
1+
use clap::{crate_version, App, AppSettings, Arg};
22
use failure::Error;
33
use jtd_infer::{HintSet, Hints, InferredSchema};
44
use serde_json::Deserializer;
@@ -9,14 +9,21 @@ use std::io::Read;
99

1010
fn main() -> Result<(), Error> {
1111
let matches = App::new("jtd-infer")
12-
.version("0.1.0")
13-
.about("Infers a JSON Type Definition schema from lines of JSON")
12+
.version(crate_version!())
13+
.about("Infers a JSON Type Definition schema from lines of JSON")
1414
.setting(AppSettings::ColoredHelp)
1515
.arg(
1616
Arg::with_name("INPUT")
1717
.help("Where to read examples from. Dash (hypen) indicates stdin")
1818
.default_value("-"),
1919
)
20+
.arg(
21+
Arg::with_name("enum-hint")
22+
.help("Advise the inferrer that the given path points to an enum. If this hint is proven wrong, a type form will be emitted instead. This flag can be provided multiple times.")
23+
.multiple(true)
24+
.number_of_values(1)
25+
.long("enum-hint"),
26+
)
2027
.arg(
2128
Arg::with_name("values-hint")
2229
.help("Advise the inferrer that the given path points to a values form. If this hint is proven wrong, a properties form will be emitted instead. This flag can be provided multiple times.")
@@ -38,6 +45,12 @@ fn main() -> Result<(), Error> {
3845
file @ _ => Box::new(File::open(file)?) as Box<dyn Read>,
3946
});
4047

48+
let enum_hints: Vec<Vec<_>> = matches
49+
.values_of("enum-hint")
50+
.unwrap_or_default()
51+
.map(parse_json_pointer)
52+
.collect();
53+
4154
let values_hints: Vec<Vec<_>> = matches
4255
.values_of("values-hint")
4356
.unwrap_or_default()
@@ -51,6 +64,7 @@ fn main() -> Result<(), Error> {
5164
.collect();
5265

5366
let hints = Hints::new(
67+
HintSet::new(enum_hints.iter().map(|p| &p[..]).collect()),
5468
HintSet::new(values_hints.iter().map(|p| &p[..]).collect()),
5569
HintSet::new(discriminator_hints.iter().map(|p| &p[..]).collect()),
5670
);

test.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)