Skip to content

Commit efaefa0

Browse files
committed
Add omitempty for fields with default in go-gen
1 parent f865a37 commit efaefa0

File tree

3 files changed

+80
-23
lines changed

3 files changed

+80
-23
lines changed

packages/go-gen/src/go.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl Display for GoField {
5050
self.ty,
5151
self.rust_name
5252
)?;
53-
if self.ty.is_nullable {
53+
if let Nullability::OmitEmpty | Nullability::Nullable = self.ty.nullability {
5454
f.write_str(",omitempty")?;
5555
}
5656
f.write_str("\"`")
@@ -60,10 +60,19 @@ impl Display for GoField {
6060
pub struct GoType {
6161
/// The name of the type in Go
6262
pub name: String,
63-
/// Whether the type should be nullable
64-
/// This will add `omitempty` to the json tag and use a pointer type if
65-
/// the type is not a basic type
66-
pub is_nullable: bool,
63+
/// Whether the type should be nullable / omitempty / etc.
64+
pub nullability: Nullability,
65+
}
66+
67+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68+
pub enum Nullability {
69+
/// The type should be nullable
70+
/// In Go, this will use a pointer type and add `omitempty` to the json tag
71+
Nullable,
72+
/// The type should not be nullable, use the type as is
73+
NonNullable,
74+
/// The type should be nullable by omitting it from the json object if it is empty
75+
OmitEmpty,
6776
}
6877

6978
impl GoType {
@@ -95,7 +104,7 @@ impl GoType {
95104

96105
impl Display for GoType {
97106
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98-
if self.is_nullable && !self.is_basic_type() {
107+
if self.nullability == Nullability::Nullable && !self.is_basic_type() {
99108
// if the type is nullable and not a basic type, use a pointer
100109
f.write_char('*')?;
101110
}
@@ -122,23 +131,23 @@ mod tests {
122131
fn go_type_display_works() {
123132
let ty = GoType {
124133
name: "string".to_string(),
125-
is_nullable: true,
134+
nullability: Nullability::Nullable,
126135
};
127136
let ty2 = GoType {
128137
name: "string".to_string(),
129-
is_nullable: false,
138+
nullability: Nullability::NonNullable,
130139
};
131140
assert_eq!(format!("{}", ty), "string");
132141
assert_eq!(format!("{}", ty2), "string");
133142

134143
let ty = GoType {
135144
name: "FooBar".to_string(),
136-
is_nullable: true,
145+
nullability: Nullability::Nullable,
137146
};
138147
assert_eq!(format!("{}", ty), "*FooBar");
139148
let ty = GoType {
140149
name: "FooBar".to_string(),
141-
is_nullable: false,
150+
nullability: Nullability::NonNullable,
142151
};
143152
assert_eq!(format!("{}", ty), "FooBar");
144153
}
@@ -150,7 +159,7 @@ mod tests {
150159
docs: None,
151160
ty: GoType {
152161
name: "string".to_string(),
153-
is_nullable: true,
162+
nullability: Nullability::Nullable,
154163
},
155164
};
156165
assert_eq!(
@@ -163,7 +172,7 @@ mod tests {
163172
docs: None,
164173
ty: GoType {
165174
name: "string".to_string(),
166-
is_nullable: false,
175+
nullability: Nullability::NonNullable,
167176
},
168177
};
169178
assert_eq!(format!("{}", field), "FooBar string `json:\"foo_bar\"`");
@@ -173,7 +182,7 @@ mod tests {
173182
docs: None,
174183
ty: GoType {
175184
name: "FooBar".to_string(),
176-
is_nullable: true,
185+
nullability: Nullability::Nullable,
177186
},
178187
};
179188
assert_eq!(
@@ -189,7 +198,7 @@ mod tests {
189198
docs: Some("foo_bar is a test field".to_string()),
190199
ty: GoType {
191200
name: "string".to_string(),
192-
is_nullable: true,
201+
nullability: Nullability::Nullable,
193202
},
194203
};
195204
assert_eq!(
@@ -208,7 +217,7 @@ mod tests {
208217
docs: None,
209218
ty: GoType {
210219
name: "string".to_string(),
211-
is_nullable: true,
220+
nullability: Nullability::Nullable,
212221
},
213222
}],
214223
};
@@ -225,7 +234,7 @@ mod tests {
225234
docs: None,
226235
ty: GoType {
227236
name: "string".to_string(),
228-
is_nullable: true,
237+
nullability: Nullability::Nullable,
229238
},
230239
}],
231240
};

packages/go-gen/src/main.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ pub fn build_enum_variant(
186186
docs,
187187
ty: GoType {
188188
name: ty,
189-
is_nullable: true, // always nullable
189+
nullability: Nullability::Nullable, // always nullable
190190
},
191191
})
192192
}
@@ -548,4 +548,40 @@ mod tests {
548548
"#,
549549
);
550550
}
551+
552+
#[test]
553+
fn serde_default_works() {
554+
fn default_u32() -> u32 {
555+
42
556+
}
557+
#[cw_serde]
558+
#[derive(Default)]
559+
struct Nested {
560+
a: u32,
561+
}
562+
#[cw_serde]
563+
struct A {
564+
#[serde(default)]
565+
payload: Binary,
566+
#[serde(default = "default_u32")]
567+
int: u32,
568+
#[serde(default)]
569+
nested: Nested,
570+
}
571+
572+
let code = generate_go(cosmwasm_schema::schema_for!(A)).unwrap();
573+
assert_code_eq(
574+
code,
575+
r#"
576+
type A struct {
577+
Int uint32 `json:"int,omitempty"`
578+
Nested Nested `json:"nested,omitempty"`
579+
Payload []byte `json:"payload,omitempty"`
580+
}
581+
type Nested struct {
582+
A uint32 `json:"a"`
583+
}
584+
"#,
585+
);
586+
}
551587
}

packages/go-gen/src/schema.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use inflector::Inflector;
44
use schemars::schema::{InstanceType, Schema, SchemaObject, SingleOrVec};
55

66
use crate::{
7-
go::{GoField, GoStruct, GoType},
7+
go::{GoField, GoStruct, GoType, Nullability},
88
utils::{replace_acronyms, suffixes},
99
};
1010

@@ -36,9 +36,21 @@ pub fn schema_object_type(
3636
type_context: TypeContext,
3737
additional_structs: &mut Vec<GoStruct>,
3838
) -> Result<GoType> {
39-
let mut is_nullable = is_null(schema);
39+
let mut nullability = if is_null(schema) {
40+
Nullability::Nullable
41+
} else {
42+
Nullability::NonNullable
43+
};
44+
45+
if schema
46+
.metadata
47+
.as_ref()
48+
.and_then(|m| m.default.as_ref())
49+
.is_some()
50+
{
51+
nullability = Nullability::OmitEmpty;
52+
}
4053

41-
// if it has a title, use that
4254
let ty = if let Some(title) = schema.metadata.as_ref().and_then(|m| m.title.as_ref()) {
4355
replace_custom_type(title)
4456
} else if let Some(reference) = &schema.reference {
@@ -56,7 +68,7 @@ pub fn schema_object_type(
5668
let nullable = nullable_type(subschemas)?;
5769
if let Some(non_null) = nullable {
5870
ensure!(subschemas.len() == 2, "multiple subschemas in anyOf");
59-
is_nullable = true;
71+
nullability = Nullability::Nullable;
6072
// extract non-null type
6173
let GoType { name, .. } =
6274
schema_object_type(non_null, type_context, additional_structs)?;
@@ -78,7 +90,7 @@ pub fn schema_object_type(
7890

7991
Ok(GoType {
8092
name: ty,
81-
is_nullable,
93+
nullability,
8294
})
8395
}
8496

@@ -197,7 +209,7 @@ pub fn type_from_instance_type(
197209
// for nullable array item types, we have to use a pointer type, even for basic types,
198210
// so we can pass null as elements
199211
// otherwise they would just be omitted from the array
200-
replace_custom_type(&if item_type.is_nullable {
212+
replace_custom_type(&if item_type.nullability == Nullability::Nullable {
201213
format!("[]*{}", item_type.name)
202214
} else {
203215
format!("[]{}", item_type.name)

0 commit comments

Comments
 (0)