Skip to content

Commit f8141a8

Browse files
authored
Add Ruby and Ruby Signatures targets (#12)
* Add a Ruby generator * Add rbs generator * Various improvements to Ruby codegen * Remove dead code
1 parent c48636a commit f8141a8

File tree

105 files changed

+5201
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+5201
-3
lines changed

Cargo.lock

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cli/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ jtd_codegen_target_csharp_system_text = { path = "../target_csharp_system_text"
1414
jtd_codegen_target_go = { path = "../target_go" }
1515
jtd_codegen_target_java_jackson = { path = "../target_java_jackson" }
1616
jtd_codegen_target_python = { path = "../target_python" }
17+
jtd_codegen_target_ruby = { path = "../target_ruby" }
18+
jtd_codegen_target_ruby_sig = { path = "../target_ruby_sig" }
1719
jtd_codegen_target_rust = { path = "../target_rust" }
1820
jtd_codegen_target_typescript = { path = "../target_typescript" }
1921
serde = "1.0"

crates/cli/src/cli.yaml

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ args:
4848
takes_value: true
4949
value_name: package
5050

51-
# Java + Jackson
51+
# Java + Jackson
5252
- java-jackson-out:
5353
help: Output directory for Java + Jackson code generation
5454
long: java-jackson-out
@@ -69,6 +69,34 @@ args:
6969
takes_value: true
7070
value_name: dir
7171

72+
# Ruby
73+
- ruby-out:
74+
help: Output directory for Ruby code generation
75+
long: ruby-out
76+
takes_value: true
77+
value_name: dir
78+
requires:
79+
- ruby-module
80+
- ruby-module:
81+
help: Module for Ruby generated types
82+
long: ruby-module
83+
takes_value: true
84+
value_name: package
85+
86+
# Ruby Signatures
87+
- ruby-sig-out:
88+
help: Output directory for Ruby Signatures code generation
89+
long: ruby-sig-out
90+
takes_value: true
91+
value_name: dir
92+
requires:
93+
- ruby-sig-module
94+
- ruby-sig-module:
95+
help: Module for Ruby Signatures generated types
96+
long: ruby-sig-module
97+
takes_value: true
98+
value_name: package
99+
72100
# Rust
73101
- rust-out:
74102
help: Output directory for Rust code generation

crates/cli/src/main.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,34 @@ fn main() -> Result<()> {
103103
log.finish("Python", &codegen_info);
104104
}
105105

106+
if let Some(out_dir) = matches.value_of("ruby-out") {
107+
log.start("Ruby", out_dir);
108+
109+
let module = matches.value_of("ruby-module").unwrap().to_owned();
110+
111+
let target = jtd_codegen_target_ruby::Target::new(module);
112+
113+
let codegen_info =
114+
jtd_codegen::codegen(&target, root_name.clone(), &schema, &Path::new(out_dir))
115+
.with_context(|| "Failed to generate Ruby code")?;
116+
117+
log.finish("Ruby", &codegen_info);
118+
}
119+
120+
if let Some(out_dir) = matches.value_of("ruby-sig-out") {
121+
log.start("Ruby Signatures", out_dir);
122+
123+
let module = matches.value_of("ruby-sig-module").unwrap().to_owned();
124+
125+
let target = jtd_codegen_target_ruby_sig::Target::new(module);
126+
127+
let codegen_info =
128+
jtd_codegen::codegen(&target, root_name.clone(), &schema, &Path::new(out_dir))
129+
.with_context(|| "Failed to generate Ruby Signatures code")?;
130+
131+
log.finish("Ruby Signatures", &codegen_info);
132+
}
133+
106134
if let Some(out_dir) = matches.value_of("rust-out") {
107135
log.start("Rust", out_dir);
108136

crates/core/src/codegen/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ impl<'a, T: Target> CodeGenerator<'a, T> {
473473
self.target
474474
.item(&mut file, &mut file_data.state, Item::Preamble)?;
475475
file.write_all(&file_data.buf)?;
476+
self.target
477+
.item(&mut file, &mut file_data.state, Item::Postamble)?;
476478

477479
Ok(())
478480
}

crates/core/src/target/inflect.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl Inflector for TailInflector {
6666
fn decompose(s: &str) -> Vec<String> {
6767
let mut out: Vec<Vec<char>> = vec![vec![]];
6868
for c in s.chars() {
69-
if c.is_whitespace() || c == '-' || c == '_' {
69+
if c.is_whitespace() || c == '-' || c == '_' || c == ':' {
7070
out.push(vec![]);
7171
continue;
7272
}
@@ -225,17 +225,22 @@ mod tests {
225225
assert_eq!(vec!["foo", "bar"], decompose("fooBar"));
226226
assert_eq!(vec!["foo", "bar"], decompose("foo-bar"));
227227
assert_eq!(vec!["foo", "bar"], decompose("foo_bar"));
228+
assert_eq!(vec!["foo", "bar"], decompose("foo::bar"));
228229
assert_eq!(vec!["foo", "bar"], decompose("FOO BAR"));
229230
assert_eq!(vec!["foo", "bar"], decompose("FOO-BAR"));
230231
assert_eq!(vec!["foo", "bar"], decompose("FOO_BAR"));
232+
assert_eq!(vec!["foo", "bar"], decompose("FOO::BAR"));
231233

232234
assert_eq!(vec!["foo", "bar", "baz"], decompose("foo barBaz"));
233235
assert_eq!(vec!["foo", "bar", "baz"], decompose("fooBar-baz"));
234236
assert_eq!(vec!["foo", "bar", "baz"], decompose("foo-bar_baz"));
235-
assert_eq!(vec!["foo", "bar", "baz"], decompose("foo_bar BAZ"));
237+
assert_eq!(vec!["foo", "bar", "baz"], decompose("foo_bar::baz"));
238+
assert_eq!(vec!["foo", "bar", "baz"], decompose("foo::bar BAZ"));
236239
assert_eq!(vec!["foo", "bar", "baz"], decompose("FOO BAR-BAZ"));
237240
assert_eq!(vec!["foo", "bar", "baz"], decompose("FOO-BAR_BAZ"));
238241
assert_eq!(vec!["foo", "bar", "baz"], decompose("FOO_BAR baz"));
242+
assert_eq!(vec!["foo", "bar", "baz"], decompose("FOO_BAR::BAZ"));
243+
assert_eq!(vec!["foo", "bar", "baz"], decompose("FOO::BAR baz"));
239244
}
240245

241246
#[test]

crates/core/src/target/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub enum Item {
9595
out_dir: PathBuf,
9696
},
9797
Preamble,
98+
Postamble,
9899
Alias {
99100
metadata: Metadata,
100101
name: String,

crates/target_csharp_system_text/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ impl jtd_codegen::target::Target for Target {
160160
None
161161
}
162162

163+
target::Item::Postamble => {
164+
None
165+
}
166+
163167
target::Item::Alias {
164168
metadata,
165169
name,

crates/target_go/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ impl jtd_codegen::target::Target for Target {
157157
None
158158
}
159159

160+
target::Item::Postamble => {
161+
None
162+
}
163+
160164
target::Item::Alias {
161165
metadata,
162166
name,

crates/target_java_jackson/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ impl jtd_codegen::target::Target for Target {
198198
None
199199
}
200200

201+
target::Item::Postamble => {
202+
None
203+
}
204+
201205
target::Item::Alias {
202206
metadata,
203207
name,

crates/target_python/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ impl jtd_codegen::target::Target for Target {
214214
None
215215
}
216216

217+
target::Item::Postamble => {
218+
None
219+
}
220+
217221
target::Item::Alias {
218222
metadata,
219223
name,

crates/target_ruby/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "jtd_codegen_target_ruby"
3+
version = "0.1.0"
4+
authors = ["Ulysse Carion <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
jtd-codegen = { path = "../core" }
9+
lazy_static = "1.4.0"
10+
serde_json = "1.0"
11+
12+
[dev-dependencies]
13+
jtd_codegen_test = { path = "../test" }

crates/target_ruby/docker/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM ruby:3.0.0
2+
3+
ARG MAIN
4+
5+
WORKDIR /work
6+
COPY /main.rb /work/main.rb
7+
8+
COPY /gen /work/gen
9+
RUN sed -i -e "s/MAIN/$MAIN/g" /work/main.rb
10+
11+
ENTRYPOINT ruby main.rb

crates/target_ruby/docker/main.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require 'json'
2+
require_relative 'gen/jtdcodegen_e2e'
3+
4+
$stdout.sync = true
5+
$stdin.each do |line|
6+
value = JTDCodegenE2E::MAIN.from_json_data(JSON.parse(line))
7+
puts JSON.generate(value.to_json_data)
8+
end
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Code generated by jtd-codegen for Ruby v0.1.0
2+
3+
require 'json'
4+
require 'time'
5+
6+
module JTDCodegenE2E
7+
8+
class Root
9+
attr_accessor :foo
10+
11+
def self.from_json_data(data)
12+
{
13+
"BAR_BAZ" => RootBarBaz,
14+
"QUUX" => RootQuux,
15+
}[data["foo"]].from_json_data(data)
16+
end
17+
end
18+
19+
class RootBarBaz < Root
20+
attr_accessor :baz
21+
22+
def self.from_json_data(data)
23+
out = RootBarBaz.new
24+
out.foo = "BAR_BAZ"
25+
out.baz = JTDCodegenE2E::from_json_data(String, data["baz"])
26+
out
27+
end
28+
29+
def to_json_data
30+
data = { "foo" => "BAR_BAZ" }
31+
data["baz"] = JTDCodegenE2E::to_json_data(baz)
32+
data
33+
end
34+
end
35+
36+
class RootQuux < Root
37+
attr_accessor :quuz
38+
39+
def self.from_json_data(data)
40+
out = RootQuux.new
41+
out.foo = "QUUX"
42+
out.quuz = JTDCodegenE2E::from_json_data(String, data["quuz"])
43+
out
44+
end
45+
46+
def to_json_data
47+
data = { "foo" => "QUUX" }
48+
data["quuz"] = JTDCodegenE2E::to_json_data(quuz)
49+
data
50+
end
51+
end
52+
53+
private
54+
55+
def self.from_json_data(type, data)
56+
if data.nil? || [Object, TrueClass, Integer, Float, String].include?(type)
57+
data
58+
elsif type == DateTime
59+
DateTime.rfc3339(data)
60+
elsif type.is_a?(Array)
61+
data.map { |elem| from_json_data(type.first, elem) }
62+
elsif type.is_a?(Hash)
63+
data.transform_values { |elem| from_json_data(type.values.first, elem) }
64+
else
65+
type.from_json_data(data)
66+
end
67+
end
68+
69+
def self.to_json_data(data)
70+
if data.nil? || [TrueClass, FalseClass, Integer, Float, String].include?(data.class)
71+
data
72+
elsif data.is_a?(DateTime)
73+
data.rfc3339
74+
elsif data.is_a?(Array)
75+
data.map { |elem| to_json_data(elem) }
76+
elsif data.is_a?(Hash)
77+
data.transform_values { |elem| to_json_data(elem) }
78+
else
79+
data.to_json_data
80+
end
81+
end
82+
end
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Code generated by jtd-codegen for Ruby v0.1.0
2+
3+
require 'json'
4+
require 'time'
5+
6+
module JTDCodegenE2E
7+
8+
class Root
9+
attr_accessor :value
10+
11+
def initialize(value)
12+
self.value = value
13+
end
14+
15+
private_class_method :new
16+
17+
BAR = new("Bar")
18+
BAZ = new("Baz")
19+
FOO = new("Foo")
20+
21+
def self.from_json_data(data)
22+
{
23+
"Bar" => BAR,
24+
"Baz" => BAZ,
25+
"Foo" => FOO,
26+
}[data]
27+
end
28+
29+
def to_json_data
30+
value
31+
end
32+
end
33+
34+
private
35+
36+
def self.from_json_data(type, data)
37+
if data.nil? || [Object, TrueClass, Integer, Float, String].include?(type)
38+
data
39+
elsif type == DateTime
40+
DateTime.rfc3339(data)
41+
elsif type.is_a?(Array)
42+
data.map { |elem| from_json_data(type.first, elem) }
43+
elsif type.is_a?(Hash)
44+
data.transform_values { |elem| from_json_data(type.values.first, elem) }
45+
else
46+
type.from_json_data(data)
47+
end
48+
end
49+
50+
def self.to_json_data(data)
51+
if data.nil? || [TrueClass, FalseClass, Integer, Float, String].include?(data.class)
52+
data
53+
elsif data.is_a?(DateTime)
54+
data.rfc3339
55+
elsif data.is_a?(Array)
56+
data.map { |elem| to_json_data(elem) }
57+
elsif data.is_a?(Hash)
58+
data.transform_values { |elem| to_json_data(elem) }
59+
else
60+
data.to_json_data
61+
end
62+
end
63+
end

0 commit comments

Comments
 (0)