Skip to content

Commit f3f338c

Browse files
committed
Add some Go codegen
1 parent 6801e88 commit f3f338c

File tree

10 files changed

+299
-96
lines changed

10 files changed

+299
-96
lines changed
+159
Original file line numberDiff line numberDiff line change
@@ -1 +1,160 @@
1+
use self::template::{
2+
EnumTemplate, EnumVariantTemplate, FieldTemplate, StructTemplate, TypeTemplate,
3+
};
4+
use heck::ToPascalCase;
5+
use std::{borrow::Cow, io};
6+
17
pub mod template;
8+
9+
fn expand_node_name<'a>(
10+
schema: &'a cw_schema::SchemaV1,
11+
node: &'a cw_schema::Node,
12+
) -> Cow<'a, str> {
13+
match node.value {
14+
cw_schema::NodeType::Array { items } => {
15+
let items = &schema.definitions[items];
16+
format!("[]{}", expand_node_name(schema, items)).into()
17+
}
18+
cw_schema::NodeType::Float => "float32".into(),
19+
cw_schema::NodeType::Double => "float64".into(),
20+
cw_schema::NodeType::Boolean => "bool".into(),
21+
cw_schema::NodeType::String => "string".into(),
22+
cw_schema::NodeType::Integer { signed, precision } => {
23+
let ty = if signed { "int" } else { "uint" };
24+
format!("{ty}{precision}").into()
25+
}
26+
cw_schema::NodeType::Binary => "[]byte".into(),
27+
cw_schema::NodeType::Optional { inner } => {
28+
let inner = &schema.definitions[inner];
29+
format!("{}", expand_node_name(schema, inner)).into()
30+
}
31+
cw_schema::NodeType::Struct(..) => node.name.as_ref().into(),
32+
cw_schema::NodeType::Tuple { items: _ } => {
33+
/*let items = items
34+
.iter()
35+
.map(|item| expand_node_name(schema, &schema.definitions[*item]))
36+
.collect::<Vec<_>>()
37+
.join(", ");
38+
39+
format!("({})", items).into()*/
40+
"[]interface{}".into()
41+
}
42+
cw_schema::NodeType::Enum { .. } => node.name.as_ref().into(),
43+
44+
cw_schema::NodeType::Decimal {
45+
precision: _,
46+
signed: _,
47+
} => {
48+
// ToDo: Actually use a decimal type here
49+
"string".into()
50+
}
51+
cw_schema::NodeType::Address => "Address".into(),
52+
cw_schema::NodeType::Checksum => "string".into(),
53+
cw_schema::NodeType::HexBinary => {
54+
// ToDo: Actually use a hex-encoded binary type here
55+
"string".into()
56+
}
57+
cw_schema::NodeType::Timestamp => "string".into(),
58+
cw_schema::NodeType::Unit => "struct{}".into(),
59+
}
60+
}
61+
62+
fn prepare_docs(desc: Option<&str>) -> Cow<'_, [Cow<'_, str>]> {
63+
desc.map(|desc| {
64+
desc.lines()
65+
.map(|line| line.replace('"', "\\\"").into())
66+
.collect()
67+
})
68+
.unwrap_or(Cow::Borrowed(&[]))
69+
}
70+
71+
pub fn process_node<O>(
72+
output: &mut O,
73+
schema: &cw_schema::SchemaV1,
74+
node: &cw_schema::Node,
75+
add_package: bool,
76+
) -> io::Result<()>
77+
where
78+
O: io::Write,
79+
{
80+
match node.value {
81+
cw_schema::NodeType::Struct(ref sty) => {
82+
let structt = StructTemplate {
83+
add_package,
84+
name: node.name.clone(),
85+
docs: prepare_docs(node.description.as_deref()),
86+
ty: match sty {
87+
cw_schema::StructType::Unit => TypeTemplate::Unit,
88+
cw_schema::StructType::Named { ref properties } => TypeTemplate::Named {
89+
fields: properties
90+
.iter()
91+
.map(|(name, prop)| FieldTemplate {
92+
name: Cow::Owned(name.to_pascal_case()),
93+
rename: Cow::Borrowed(name),
94+
docs: prepare_docs(prop.description.as_deref()),
95+
ty: expand_node_name(schema, &schema.definitions[prop.value]),
96+
})
97+
.collect(),
98+
},
99+
cw_schema::StructType::Tuple { ref items } => TypeTemplate::Tuple(
100+
items
101+
.iter()
102+
.map(|item| expand_node_name(schema, &schema.definitions[*item]))
103+
.collect(),
104+
),
105+
},
106+
};
107+
108+
writeln!(output, "{structt}")?;
109+
}
110+
cw_schema::NodeType::Enum { ref cases, .. } => {
111+
let enumm = EnumTemplate {
112+
add_package,
113+
name: node.name.clone(),
114+
docs: prepare_docs(node.description.as_deref()),
115+
variants: cases
116+
.iter()
117+
.map(|(name, case)| EnumVariantTemplate {
118+
name: name.to_pascal_case().into(),
119+
rename: Cow::Borrowed(name),
120+
docs: prepare_docs(case.description.as_deref()),
121+
ty: match case.value {
122+
cw_schema::EnumValue::Unit => TypeTemplate::Unit,
123+
cw_schema::EnumValue::Tuple { ref items } => {
124+
let items = items
125+
.iter()
126+
.map(|item| {
127+
expand_node_name(schema, &schema.definitions[*item])
128+
})
129+
.collect();
130+
131+
TypeTemplate::Tuple(items)
132+
}
133+
cw_schema::EnumValue::Named { ref properties, .. } => {
134+
TypeTemplate::Named {
135+
fields: properties
136+
.iter()
137+
.map(|(name, prop)| FieldTemplate {
138+
name: Cow::Owned(name.to_pascal_case()),
139+
rename: Cow::Borrowed(name),
140+
docs: prepare_docs(prop.description.as_deref()),
141+
ty: expand_node_name(
142+
schema,
143+
&schema.definitions[prop.value],
144+
),
145+
})
146+
.collect(),
147+
}
148+
}
149+
},
150+
})
151+
.collect(),
152+
};
153+
154+
writeln!(output, "{enumm}")?;
155+
}
156+
_ => (),
157+
}
158+
159+
Ok(())
160+
}

packages/cw-schema-codegen/src/go/template.rs

+4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ use std::borrow::Cow;
44
#[derive(Clone)]
55
pub struct EnumVariantTemplate<'a> {
66
pub name: Cow<'a, str>,
7+
pub rename: Cow<'a, str>,
78
pub docs: Cow<'a, [Cow<'a, str>]>,
89
pub ty: TypeTemplate<'a>,
910
}
1011

1112
#[derive(Template)]
1213
#[template(escape = "none", path = "go/enum.tpl.go")]
1314
pub struct EnumTemplate<'a> {
15+
pub add_package: bool,
1416
pub name: Cow<'a, str>,
1517
pub docs: Cow<'a, [Cow<'a, str>]>,
1618
pub variants: Cow<'a, [EnumVariantTemplate<'a>]>,
@@ -19,6 +21,7 @@ pub struct EnumTemplate<'a> {
1921
#[derive(Clone)]
2022
pub struct FieldTemplate<'a> {
2123
pub name: Cow<'a, str>,
24+
pub rename: Cow<'a, str>,
2225
pub docs: Cow<'a, [Cow<'a, str>]>,
2326
pub ty: Cow<'a, str>,
2427
}
@@ -35,6 +38,7 @@ pub enum TypeTemplate<'a> {
3538
#[derive(Template)]
3639
#[template(escape = "none", path = "go/struct.tpl.go")]
3740
pub struct StructTemplate<'a> {
41+
pub add_package: bool,
3842
pub name: Cow<'a, str>,
3943
pub docs: Cow<'a, [Cow<'a, str>]>,
4044
pub ty: TypeTemplate<'a>,

packages/cw-schema-codegen/src/main.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ fn generate_defs<W>(
5757
output: &mut W,
5858
language: Language,
5959
schema: &cw_schema::Schema,
60-
add_imports: bool,
60+
add_imports_or_package: bool,
6161
) -> anyhow::Result<()>
6262
where
6363
W: io::Write,
@@ -72,10 +72,10 @@ where
7272
match language {
7373
Language::Rust => cw_schema_codegen::rust::process_node(output, schema, node),
7474
Language::Typescript => {
75-
cw_schema_codegen::typescript::process_node(output, schema, node, add_imports)
75+
cw_schema_codegen::typescript::process_node(output, schema, node, add_imports_or_package)
7676
}
7777
Language::Python => cw_schema_codegen::python::process_node(output, schema, node),
78-
Language::Go => todo!(),
78+
Language::Go => cw_schema_codegen::go::process_node(output, schema, node, add_imports_or_package),
7979
}
8080
})?;
8181

packages/cw-schema-codegen/src/python/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ fn expand_node_name<'a>(
4242
cw_schema::NodeType::HexBinary => todo!(),
4343
cw_schema::NodeType::Timestamp => todo!(),
4444
cw_schema::NodeType::Unit => "None".into(),
45-
_ => todo!(),
4645
}
4746
}
4847

@@ -82,7 +81,6 @@ where
8281
.map(|item| expand_node_name(schema, &schema.definitions[*item]))
8382
.collect(),
8483
),
85-
_ => todo!(),
8684
},
8785
};
8886

@@ -124,7 +122,6 @@ where
124122
.collect(),
125123
}
126124
}
127-
_ => todo!(),
128125
},
129126
})
130127
.collect(),
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,39 @@
11
// This code is @generated by cw-schema-codegen. Do not modify this manually.
22

3+
{% if add_package %}
4+
package cwcodegen
5+
6+
import (
7+
"github.com/cosmos/cosmos-sdk/types/address"
8+
)
9+
{% endif %}
10+
11+
{% for variant in variants %}
12+
{% match variant.ty %}
13+
{% when TypeTemplate::Unit %}
14+
type {{ name }}{{ variant.name }} struct{}
15+
{% when TypeTemplate::Tuple(types) %}
16+
type {{ name }}{{ variant.name }} []interface{}
17+
{% when TypeTemplate::Named { fields } %}
18+
type {{ name }}{{ variant.name }} struct {
19+
{% for field in fields %}
20+
{% for doc in docs %}
21+
// {{ doc }}
22+
{% endfor %}
23+
{{ field.name }} {{ field.ty }} `json:"{{ field.rename }}"`
24+
{% endfor %}
25+
}
26+
{% endmatch %}
27+
{% endfor %}
28+
29+
{% for doc in docs %}
30+
// {{ doc }}
31+
{% endfor %}
32+
type {{ name }} struct {
33+
{% for variant in variants %}
34+
{% for doc in docs %}
35+
// {{ doc }}
36+
{% endfor %}
37+
{{ variant.name}} {{ name }}{{ variant.name }} `json:"{{ variant.rename }}"`
38+
{% endfor %}
39+
}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11
// This code is @generated by cw-schema-codegen. Do not modify this manually.
22

3+
{% if add_package %}
34
package cwcodegen
45

6+
import (
7+
"github.com/cosmos/cosmos-sdk/types"
8+
)
9+
{% endif %}
10+
511
{% for doc in docs %}
612
// {{ doc }}
713
{% endfor %}
14+
{% match ty %}
15+
{% when TypeTemplate::Unit %}
16+
type {{ name }} struct{}
17+
{% when TypeTemplate::Tuple with (types) %}
18+
type {{ name }} []interface{} /* todo: replace with true tuples if i can think of it */
19+
{% when TypeTemplate::Named with { fields } %}
820
type {{ name }} struct {
9-
{% match ty %}
10-
{% when TypeTemplate::Unit %}
11-
{% when TypeTemplate::Tuple with (types) %}
12-
{{ todo!() }}
13-
{% when TypeTemplate::Named with { fields } %}
14-
{% for field in fields %}
15-
{% for doc in docs %}
16-
// {{ doc }}
17-
{% endfor %}
18-
{{ field.name|capitalize }} {{ field.ty }} `json:"{{ field.name }}"`
19-
{% endfor %}
20-
{% endmatch %}
21+
{% for field in fields %}
22+
{% for doc in docs %}
23+
// {{ doc }}
24+
{% endfor %}
25+
{{ field.name }} {{ field.ty }} `json:"{{ field.rename }}"`
26+
{% endfor %}
2127
}
28+
{% endmatch %}

packages/cw-schema-codegen/templates/rust/enum.tpl.rs

+27-28
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,34 @@
66

77
#[cosmwasm_schema::cw_serde]
88
pub enum {{ name }} {
9-
{% for variant in variants %}
10-
{% for doc in variant.docs %}
11-
#[doc = "{{ doc }}"]
12-
{% endfor %}
13-
14-
{% match variant.serde_rename %}
15-
{% when Some with (rename) %}
16-
#[serde(rename = "{{ rename }}")]
17-
{% when None %}
18-
{% endmatch %}
9+
{% for variant in variants %}
10+
{% for doc in variant.docs %}
11+
#[doc = "{{ doc }}"]
12+
{% endfor %}
1913

20-
{{ variant.name }}
21-
{% match variant.ty %}
22-
{% when TypeTemplate::Unit %}
23-
{% when TypeTemplate::Tuple with (types) %}
24-
(
25-
{{ types|join(", ") }}
26-
)
27-
{% when TypeTemplate::Named with { fields } %}
28-
{
29-
{% for field in fields %}
30-
{% for doc in field.docs %}
31-
#[doc = "{{ doc }}"]
32-
{% endfor %}
14+
{% match variant.serde_rename %}
15+
{% when Some with (rename) %}
16+
#[serde(rename = "{{ rename }}")]
17+
{% when None %}
18+
{% endmatch %}
3319

34-
{{ field.name }}: {{ field.ty }},
35-
{% endfor %}
36-
}
37-
{% endmatch %}
20+
{{ variant.name }}
21+
{% match variant.ty %}
22+
{% when TypeTemplate::Unit %}
23+
{% when TypeTemplate::Tuple with (types) %}
24+
(
25+
{{ types|join(", ") }}
26+
)
27+
{% when TypeTemplate::Named with { fields } %}
28+
{
29+
{% for field in fields %}
30+
{% for doc in field.docs %}
31+
#[doc = "{{ doc }}"]
32+
{% endfor %}
33+
{{ field.name }}: {{ field.ty }},
34+
{% endfor %}
35+
}
36+
{% endmatch %}
3837
,
39-
{% endfor %}
38+
{% endfor %}
4039
}

0 commit comments

Comments
 (0)