Skip to content

Commit d769b62

Browse files
committed
Generate Go interfaces for discriminators
This commit implements /issues/67.
1 parent a42555d commit d769b62

File tree

1 file changed

+44
-24
lines changed

1 file changed

+44
-24
lines changed

crates/target_go/src/lib.rs

+44-24
Original file line numberDiff line numberDiff line change
@@ -258,32 +258,51 @@ impl jtd_codegen::target::Target for Target {
258258

259259
writeln!(out)?;
260260
write!(out, "{}", description(&metadata, 0))?;
261-
writeln!(out, "type {} struct {{", name)?;
262-
writeln!(out, "\t{} string", tag_field_name)?;
261+
writeln!(out, "type {} interface {{", name)?;
262+
writeln!(out, "\tjson.Marshaler")?;
263+
writeln!(out, "\t{}() string", tag_field_name)?;
264+
writeln!(out, "\tis{}()", name)?;
265+
writeln!(out, "}}")?;
266+
writeln!(out)?;
267+
263268
for variant in &variants {
264-
writeln!(out)?;
265-
writeln!(out, "\t{} {}", &variant.field_name, &variant.type_name)?;
269+
writeln!(out, "func ({}) {}() string {{ return {:?} }}", variant.type_name, tag_field_name, variant.tag_value)?;
266270
}
267-
writeln!(out, "}}")?;
271+
writeln!(out)?;
268272

273+
for variant in &variants {
274+
writeln!(out, "func ({}) is{}() {{}}", variant.type_name, name)?;
275+
}
269276
writeln!(out)?;
270-
writeln!(out, "func (v {}) MarshalJSON() ([]byte, error) {{", name)?;
271-
writeln!(out, "\tswitch v.{} {{", tag_field_name)?;
277+
272278
for variant in &variants {
273-
writeln!(out, "\tcase {:?}:", variant.tag_value)?;
274-
writeln!(out, "\t\treturn json.Marshal(struct {{ T string `json:\"{}\"`; {} }}{{ v.{}, v.{} }})", tag_json_name, variant.type_name, tag_field_name, variant.field_name)?;
279+
writeln!(out, "func (v {}) MarshalJSON() ([]byte, error) {{", variant.type_name)?;
280+
writeln!(out, "\ttype Alias {}", variant.type_name)?;
281+
writeln!(out, "\treturn json.Marshal(struct {{")?;
282+
writeln!(out, "\t\tT string `json:\"{}\"`", tag_json_name)?;
283+
writeln!(out, "\t\tAlias")?;
284+
writeln!(out, "\t}}{{")?;
285+
writeln!(out, "\t\tv.{}(),", tag_field_name)?;
286+
writeln!(out, "\t\tAlias(v),")?;
287+
writeln!(out, "\t}})")?;
288+
writeln!(out, "}}")?;
289+
writeln!(out)?;
275290
}
276-
writeln!(out, "\t}}")?;
291+
277292
writeln!(out)?;
278-
writeln!(
279-
out,
280-
"\treturn nil, fmt.Errorf(\"bad {0} value: %s\", v.{0})",
281-
tag_field_name
282-
)?;
293+
writeln!(out, "// {}JSON wraps the interface that it embeds. It can be", name)?;
294+
writeln!(out, "// the following types:")?;
295+
writeln!(out, "//")?;
296+
for variant in &variants {
297+
writeln!(out, "\t// - [{}] ({})", &variant.type_name, &variant.tag_value)?;
298+
}
299+
writeln!(out, "//")?;
300+
writeln!(out, "type {}JSON struct {{", name)?;
301+
writeln!(out, "\t{}", name)?;
283302
writeln!(out, "}}")?;
284303

285304
writeln!(out)?;
286-
writeln!(out, "func (v *{}) UnmarshalJSON(b []byte) error {{", name)?;
305+
writeln!(out, "func (v *{}JSON) UnmarshalJSON(b []byte) error {{", name)?;
287306
writeln!(
288307
out,
289308
"\tvar t struct {{ T string `json:\"{}\"` }}",
@@ -293,29 +312,30 @@ impl jtd_codegen::target::Target for Target {
293312
writeln!(out, "\t\treturn err")?;
294313
writeln!(out, "\t}}")?;
295314
writeln!(out)?;
315+
writeln!(out, "\tvar value {}", name)?;
296316
writeln!(out, "\tvar err error")?;
317+
writeln!(out)?;
297318
writeln!(out, "\tswitch t.T {{")?;
298319
for variant in &variants {
299320
writeln!(out, "\tcase {:?}:", variant.tag_value)?;
300-
writeln!(
301-
out,
302-
"\t\terr = json.Unmarshal(b, &v.{})",
303-
variant.field_name
304-
)?;
321+
writeln!(out, "\t\tvar v {}", variant.type_name)?;
322+
writeln!(out, "\t\terr = json.Unmarshal(b, &v)")?;
323+
writeln!(out, "\t\tvalue = v")?;
305324
}
306325
writeln!(out, "\tdefault:")?;
307326
writeln!(
308327
out,
309-
"\t\terr = fmt.Errorf(\"bad {} value: %s\", t.T)",
310-
tag_field_name
328+
"\t\terr = fmt.Errorf(\"{}: bad {} value: %q\", t.T)",
329+
name,
330+
tag_json_name
311331
)?;
312332
writeln!(out, "\t}}")?;
313333
writeln!(out)?;
314334
writeln!(out, "\tif err != nil {{")?;
315335
writeln!(out, "\t\treturn err")?;
316336
writeln!(out, "\t}}")?;
317337
writeln!(out)?;
318-
writeln!(out, "\tv.{} = t.T", tag_field_name)?;
338+
writeln!(out, "\tv.{} = value", name)?;
319339
writeln!(out, "\treturn nil")?;
320340
writeln!(out, "}}")?;
321341

0 commit comments

Comments
 (0)