@@ -25,6 +25,24 @@ pub struct Go {
25
25
/// Whether or not to exclude the version header that normally appears at the top of generated code.
26
26
/// If you aren't generating a snapshot test, this setting can just be left as a default (false)
27
27
pub no_version_header : bool ,
28
+ /// Whether or not slices should be translated with a pointer redirection.
29
+ ///
30
+ /// It is rather unusual in Go to have pointers to slices. This is because, in Go, slices are already reference types.
31
+ /// However, an edge case can occur:
32
+ ///
33
+ /// type A struct {
34
+ /// Slice []string `json:",omitempty"`
35
+ /// }
36
+ ///
37
+ /// type B struct {
38
+ /// Slice *[]string `json:",omitempty"`
39
+ /// }
40
+ /// For type A, both Slice: nil and Slice: []string{} have the same JSON serialisation (Slice is omitted).
41
+ /// For type B Slice: nil and Slice: []string{} both have a different JSON serialisation.
42
+ /// In the first case, Slice is omitted. In the second case the field has the value [].
43
+ ///
44
+ /// This, however, is rarely applicable in practice, and having this feature does not justify exposing an unintuitive user interface.
45
+ pub no_pointer_slice : bool ,
28
46
}
29
47
30
48
impl Language for Go {
@@ -102,7 +120,15 @@ impl Language for Go {
102
120
format ! ( "[]{}" , self . format_type( rtype, generic_types) ?)
103
121
}
104
122
SpecialRustType :: Option ( rtype) => {
105
- format ! ( "*{}" , self . format_type( rtype, generic_types) ?)
123
+ format ! (
124
+ "{}{}" ,
125
+ if rtype. is_vec( ) && self . no_pointer_slice {
126
+ ""
127
+ } else {
128
+ "*"
129
+ } ,
130
+ self . format_type( rtype, generic_types) ?
131
+ )
106
132
}
107
133
SpecialRustType :: HashMap ( rtype1, rtype2) => format ! (
108
134
"map[{}]{}" ,
@@ -505,3 +531,27 @@ fn convert_acronyms_to_uppercase(uppercase_acronyms: Vec<String>, name: &str) ->
505
531
}
506
532
res
507
533
}
534
+
535
+ mod test {
536
+ #[ test]
537
+ fn no_pointer_slice ( ) {
538
+ let mut go = super :: Go {
539
+ ..Default :: default ( )
540
+ } ;
541
+
542
+ let optional_slice = super :: SpecialRustType :: Option ( Box :: new (
543
+ crate :: rust_types:: RustType :: Special ( super :: SpecialRustType :: Vec ( Box :: new (
544
+ crate :: rust_types:: RustType :: Special ( super :: SpecialRustType :: I32 ) ,
545
+ ) ) ) ,
546
+ ) ) ;
547
+
548
+ // by default, optional slices should be translated with a pointer redirection
549
+ let go_slice = super :: Language :: format_special_type ( & mut go, & optional_slice, & [ ] ) . unwrap ( ) ;
550
+ assert_eq ! ( go_slice, "*[]int" ) ;
551
+
552
+ // when specifically opting out of this via the config, the pointer redirection should be omitted
553
+ go. no_pointer_slice = true ;
554
+ let go_slice = super :: Language :: format_special_type ( & mut go, & optional_slice, & [ ] ) . unwrap ( ) ;
555
+ assert_eq ! ( go_slice, "[]int" ) ;
556
+ }
557
+ }
0 commit comments