-
Notifications
You must be signed in to change notification settings - Fork 192
Preprocessor Directives
You can make tweaks to how the code generator generates methods using directives in your source code comments. All directives take the form
//msgp:directive [arg1] [arg2] [arg3]...
much like the gc
compiler directives.
There are two flavors of directives: global and pass-specific.
//msgp:ignore Type1 Type2 Type3
Ignore tells the code generator not to generate methods for the list of types supplied.
//msgp:tuple TypeA
type TypeA struct {
Left float64
Right float64
}
The msgp:tuple
directive tells the generator to generate code for the struct so that it is serialized as an array instead of a map. In other words, TypeA{1.0, 2.0}
above would be encoded as
[1.0,2.0]
instead of
{"Left":1.0,"Right":2.0}
For smaller objects, tuple encoding can yield serious performance improvements.
//msgp:shim Enum as:string using:(Enum).String/parseString
type Enum byte
const(
A Enum = iota
B
C
D
invalid
)
func (e Enum) String() string {
switch e {
case A:
return "A"
case B:
return "B"
case C:
return "C"
case D:
return "D"
default:
return "<invalid>"
}
}
func parseString(s string) Enum {
switch s {
case "A":
return A
case "B":
return B
case "C":
return C
case "D":
return D
default:
return invalid
}
}
The shim
directive lets you inline a type-conversion function for a user-defined type in order to have it encode and decode differently than the default for its concrete type. In the example above, we're using the shim
directive to translate a const-iota
block into strings for encoding and decoding. Note that the as:
argument must take a "base" type (a built-in, []byte
, interface{}
, msgp.Extension
or a type already processed by the code generator.)
the replace
directive makes it easier to serialize foreign types.
Example usage with github.com/google/uuid
package main
import "github.com/google/uuid"
//go:generate msgp
//msgp:replace uuid.UUID with:UUID
type UUID [16]byte
// Or like that
//msgp:replace uuid.UUID with:[16]byte
type User struct {
ID uuid.UUID
}
This can also be used to replace serialization of external types with internal types.
For example //msgp:replace cpu.TimesStat with:cpuTimesStat
will replace an external type cpu.TimesStat
with a
local cpuTimesStat
, which should be a copy of the external struct, that has generated functions.
A pass-specific directive operates on one particular code generation pass. They take the form
//msgp:passname directives [arg1] [arg2] ...
The valid pass names are as follows:
encode
decode
marshal
unmarshal
size
test
The ignore
directive can be applied to a particular combination of pass and type when invoked like:
//msgp:encode ignore Type1 Type2...
Methods that are ignore
d also do not produce test cases. (The code generator is aware of the dependency.)
Ignore can be particularly useful when you don't want the code generator to clobber an existing manually-written implementation of one of the methods.