Skip to content

Commit 9950f9a

Browse files
committed
Initial commit
0 parents  commit 9950f9a

File tree

9 files changed

+294
-0
lines changed

9 files changed

+294
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
**/*.rs.bk
3+
Cargo.lock

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "jtd"
3+
version = "0.1.0"
4+
authors = ["JSON Type Definition Contributors"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
serde = { version = "1.0", features = ["derive"] }
9+
serde_json = "1.0"

fuzz/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
target
3+
corpus
4+
artifacts

fuzz/Cargo.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
[package]
3+
name = "jtd-fuzz"
4+
version = "0.0.0"
5+
authors = ["Automatically generated"]
6+
publish = false
7+
edition = "2018"
8+
9+
[package.metadata]
10+
cargo-fuzz = true
11+
12+
[dependencies]
13+
libfuzzer-sys = "0.3"
14+
15+
[dependencies.jtd]
16+
path = ".."
17+
18+
# Prevent this from interfering with workspaces
19+
[workspace]
20+
members = ["."]
21+
22+
[[bin]]
23+
name = "fuzz_target_1"
24+
path = "fuzz_targets/fuzz_target_1.rs"

fuzz/fuzz_targets/fuzz_target_1.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![no_main]
2+
use libfuzzer_sys::fuzz_target;
3+
4+
fuzz_target!(|data: &[u8]| {
5+
// fuzzed code goes here
6+
});

src/form.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use crate::schema::Schema;
2+
use std::collections::HashMap;
3+
use std::collections::HashSet;
4+
5+
pub enum Form {
6+
Empty(Empty),
7+
Type(Type),
8+
Enum(Enum),
9+
Elements(Elements),
10+
Properties(Properties),
11+
Values(Values),
12+
Discriminator(Discriminator),
13+
}
14+
15+
pub struct Empty {}
16+
17+
pub struct Type {
18+
pub nullable: bool,
19+
pub type_value: TypeValue,
20+
}
21+
22+
pub enum TypeValue {
23+
Boolean,
24+
Float32,
25+
Float64,
26+
Int8,
27+
Uint8,
28+
Int16,
29+
Uint16,
30+
Int32,
31+
Uint32,
32+
String,
33+
Timestamp,
34+
}
35+
36+
pub struct Enum {
37+
pub nullable: bool,
38+
pub values: HashSet<String>,
39+
}
40+
41+
pub struct Elements {
42+
pub nullable: bool,
43+
pub schema: Box<Schema>,
44+
}
45+
46+
pub struct Properties {
47+
pub nullable: bool,
48+
pub required: HashMap<String, Schema>,
49+
pub optional: HashMap<String, Schema>,
50+
pub additional: bool,
51+
pub has_required: bool,
52+
}
53+
54+
pub struct Values {
55+
pub nullable: bool,
56+
pub schema: Box<Schema>,
57+
}
58+
59+
pub struct Discriminator {
60+
pub nullable: bool,
61+
pub tag: String,
62+
pub mapping: HashMap<String, Schema>,
63+
}

src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pub mod form;
2+
pub mod schema;
3+
pub mod serde;
4+
5+
pub use form::Form;
6+
pub use schema::Schema;
7+
8+
#[cfg(test)]
9+
mod tests {
10+
#[test]
11+
fn it_works() {
12+
assert_eq!(2 + 2, 4);
13+
}
14+
}

src/schema.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use crate::form::Form;
2+
use std::collections::HashMap;
3+
4+
pub struct Schema {
5+
pub definitions: HashMap<String, Schema>,
6+
pub form: Form,
7+
}

src/serde.rs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
use serde::{Deserialize, Serialize};
2+
use std::collections::HashMap;
3+
4+
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Eq)]
5+
#[serde(rename_all = "camelCase")]
6+
pub struct Schema {
7+
pub definitions: Option<HashMap<String, Schema>>,
8+
pub nullable: Option<bool>,
9+
pub type_: Option<String>,
10+
pub enum_: Option<Vec<String>>,
11+
pub elements: Option<Box<Schema>>,
12+
pub properties: Option<HashMap<String, Schema>>,
13+
pub optional_properties: Option<HashMap<String, Schema>>,
14+
pub values: Option<Box<Schema>>,
15+
pub discriminator: Option<Discriminator>,
16+
}
17+
18+
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Eq)]
19+
pub struct Discriminator {
20+
pub tag: String,
21+
pub mapping: HashMap<String, Schema>,
22+
}
23+
24+
#[cfg(test)]
25+
mod tests {
26+
use serde_json::json;
27+
28+
#[test]
29+
fn parse_empty() {
30+
assert_eq!(
31+
super::Schema::default(),
32+
serde_json::from_value(json!({})).unwrap()
33+
);
34+
}
35+
36+
#[test]
37+
fn parse_partial() {
38+
assert_eq!(
39+
super::Schema {
40+
nullable: Some(true),
41+
optional_properties: Some(
42+
vec![(
43+
"foo".to_owned(),
44+
super::Schema {
45+
type_: Some("uint32".to_owned()),
46+
..Default::default()
47+
}
48+
)]
49+
.into_iter()
50+
.collect()
51+
),
52+
..Default::default()
53+
},
54+
serde_json::from_value(json!({
55+
"optionalProperties": {
56+
"foo": {
57+
"type": "uint32",
58+
},
59+
},
60+
"nullable": true,
61+
}))
62+
.unwrap()
63+
);
64+
}
65+
66+
#[test]
67+
fn parse_full() {
68+
assert_eq!(
69+
super::Schema {
70+
definitions: Some(
71+
vec![(
72+
"foo".to_owned(),
73+
super::Schema {
74+
type_: Some("uint32".to_owned()),
75+
..Default::default()
76+
}
77+
)]
78+
.into_iter()
79+
.collect()
80+
),
81+
nullable: Some(true),
82+
type_: Some("uint32".to_owned()),
83+
enum_: Some(vec!["foo".to_owned(), "bar".to_owned()]),
84+
elements: Some(Box::new(super::Schema {
85+
type_: Some("uint32".to_owned()),
86+
..Default::default()
87+
})),
88+
properties: Some(
89+
vec![(
90+
"foo".to_owned(),
91+
super::Schema {
92+
type_: Some("uint32".to_owned()),
93+
..Default::default()
94+
}
95+
)]
96+
.into_iter()
97+
.collect()
98+
),
99+
optional_properties: Some(
100+
vec![(
101+
"foo".to_owned(),
102+
super::Schema {
103+
type_: Some("uint32".to_owned()),
104+
..Default::default()
105+
}
106+
)]
107+
.into_iter()
108+
.collect()
109+
),
110+
values: Some(Box::new(super::Schema {
111+
type_: Some("uint32".to_owned()),
112+
..Default::default()
113+
})),
114+
discriminator: Some(super::Discriminator {
115+
tag: "foo".to_owned(),
116+
mapping: vec![(
117+
"foo".to_owned(),
118+
super::Schema {
119+
type_: Some("uint32".to_owned()),
120+
..Default::default()
121+
}
122+
)]
123+
.into_iter()
124+
.collect(),
125+
}),
126+
},
127+
serde_json::from_value(json!({
128+
"definitions": {
129+
"foo": {
130+
"type": "uint32",
131+
},
132+
},
133+
"nullable": true,
134+
"type": "uint32",
135+
"enum": ["foo", "bar"],
136+
"elements": {
137+
"type": "uint32",
138+
},
139+
"properties": {
140+
"foo": {
141+
"type": "uint32",
142+
},
143+
},
144+
"optionalProperties": {
145+
"foo": {
146+
"type": "uint32",
147+
},
148+
},
149+
"values": {
150+
"type": "uint32",
151+
},
152+
"discriminator": {
153+
"tag": "foo",
154+
"mapping": {
155+
"foo": {
156+
"type": "uint32",
157+
},
158+
},
159+
},
160+
}))
161+
.unwrap()
162+
);
163+
}
164+
}

0 commit comments

Comments
 (0)