Package marshalto
Overview ▹
Overview ▾
The marshalto plugin generates a Marshal and MarshalTo method for each message. The `Marshal() ([]byte, error)` method results in the fact that the message implements the Marshaler interface. This allows proto.Marshal to be faster by calling the generated Marshal method rather than using reflect to Marshal the struct.
If is enabled by the following extensions:
- marshaler - marshaler_all
Or the following extensions:
- unsafe_marshaler - unsafe_marshaler_all
That is if you want to use the unsafe package in your generated code. The speed up using the unsafe package is not very significant.
The generation of marshalling tests are enabled using one of the following extensions:
- testgen - testgen_all
And benchmarks given it is enabled using one of the following extensions:
- benchgen - benchgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.marshaler_all) = true;
message B {
option (gogoproto.description) = true; optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true]; repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the marshalto plugin, will generate the following code:
func (m *B) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalTo(dAtA) if err != nil { return nil, err } return dAtA[:n], nil } func (m *B) MarshalTo(dAtA []byte) (int, error) { var i int _ = i var l int _ = l dAtA[i] = 0xa i++ i = encodeVarintExample(dAtA, i, uint64(m.A.Size())) n2, err := m.A.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n2 if len(m.G) > 0 { for _, msg := range m.G { dAtA[i] = 0x12 i++ i = encodeVarintExample(dAtA, i, uint64(msg.Size())) n, err := msg.MarshalTo(dAtA[i:]) if err != nil { return 0, err } i += n } } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } return i, nil }
As shown above Marshal calculates the size of the not yet marshalled message and allocates the appropriate buffer. This is followed by calling the MarshalTo method which requires a preallocated buffer. The MarshalTo method allows a user to rather preallocated a reusable buffer.
The Size method is generated using the size plugin and the gogoproto.sizer, gogoproto.sizer_all extensions. The user can also using the generated Size method to check that his reusable buffer is still big enough.
The generated tests and benchmarks will keep you safe and show that this is really a significant speed improvement.
An additional message-level option `stable_marshaler` (and the file-level option `stable_marshaler_all`) exists which causes the generated marshalling code to behave deterministically. Today, this only changes the serialization of maps; they are serialized in sort order.
Index ▹
Internal call graph ▹
Internal call graph ▾
In the call graph viewer below, each node is a function belonging to this package and its children are the functions it calls—perhaps dynamically.
The root nodes are the entry points of the package: functions that may be called from outside the package. There may be non-exported or anonymous functions among them if they are called dynamically from another package.
Click a node to visit that function's source code.
From there you can visit its callers by
clicking its declaring func
token.
Functions may be omitted if they were determined to be unreachable in the particular programs or tests that were analyzed.
func NewMarshal ¶
func NewMarshal() *marshalto
func NewUnsafeMarshal ¶
func NewUnsafeMarshal() *marshalto
type NumGen ¶
type NumGen interface { Next() string Current() string }
func NewNumGen ¶
func NewNumGen() NumGen
Portions of this page are modifications based on work created and shared by Google
and used according to terms described in the Creative Commons 3.0 Attribution License.
© 2018 ActiveState Software Inc. All rights reserved. Trademarks.