github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/tools/go_marshal/gomarshal/generator_interfaces_dynamic.go (about)

     1  // Copyright 2021 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package gomarshal
    16  
    17  func (g *interfaceGenerator) emitMarshallableForDynamicType() {
    18  	// The user writes their own MarshalBytes, UnmarshalBytes and SizeBytes for
    19  	// dynamic types. Generate the rest using these definitions.
    20  
    21  	g.emit("// Packed implements marshal.Marshallable.Packed.\n")
    22  	g.emit("//go:nosplit\n")
    23  	g.emit("func (%s *%s) Packed() bool {\n", g.r, g.typeName())
    24  	g.inIndent(func() {
    25  		g.emit("// Type %s is dynamic so it might have slice/string headers. Hence, it is not packed.\n", g.typeName())
    26  		g.emit("return false\n")
    27  	})
    28  	g.emit("}\n\n")
    29  
    30  	g.emit("// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.\n")
    31  	g.emit("func (%s *%s) MarshalUnsafe(dst []byte) {\n", g.r, g.typeName())
    32  	g.inIndent(func() {
    33  		g.emit("// Type %s doesn't have a packed layout in memory, fallback to MarshalBytes.\n", g.typeName())
    34  		g.emit("%s.MarshalBytes(dst)\n", g.r)
    35  	})
    36  	g.emit("}\n\n")
    37  
    38  	g.emit("// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.\n")
    39  	g.emit("func (%s *%s) UnmarshalUnsafe(src []byte) {\n", g.r, g.typeName())
    40  	g.inIndent(func() {
    41  		g.emit("// Type %s doesn't have a packed layout in memory, fallback to UnmarshalBytes.\n", g.typeName())
    42  		g.emit("%s.UnmarshalBytes(src)\n", g.r)
    43  	})
    44  	g.emit("}\n\n")
    45  
    46  	g.emit("// CopyOutN implements marshal.Marshallable.CopyOutN.\n")
    47  	g.emit("//go:nosplit\n")
    48  	g.recordUsedImport("marshal")
    49  	g.recordUsedImport("hostarch")
    50  	g.emit("func (%s *%s) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {\n", g.r, g.typeName())
    51  	g.inIndent(func() {
    52  		g.emit("// Type %s doesn't have a packed layout in memory, fall back to MarshalBytes.\n", g.typeName())
    53  		g.emit("buf := cc.CopyScratchBuffer(%s.SizeBytes()) // escapes: okay.\n", g.r)
    54  		g.emit("%s.MarshalBytes(buf) // escapes: fallback.\n", g.r)
    55  		g.emit("return cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.\n")
    56  	})
    57  	g.emit("}\n\n")
    58  
    59  	g.emit("// CopyOut implements marshal.Marshallable.CopyOut.\n")
    60  	g.emit("//go:nosplit\n")
    61  	g.recordUsedImport("marshal")
    62  	g.recordUsedImport("hostarch")
    63  	g.emit("func (%s *%s) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {\n", g.r, g.typeName())
    64  	g.inIndent(func() {
    65  		g.emit("return %s.CopyOutN(cc, addr, %s.SizeBytes())\n", g.r, g.r)
    66  	})
    67  	g.emit("}\n\n")
    68  
    69  	g.emit("// CopyIn implements marshal.Marshallable.CopyIn.\n")
    70  	g.emit("//go:nosplit\n")
    71  	g.recordUsedImport("marshal")
    72  	g.recordUsedImport("hostarch")
    73  	g.emit("func (%s *%s) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {\n", g.r, g.typeName())
    74  	g.inIndent(func() {
    75  		g.emit("// Type %s doesn't have a packed layout in memory, fall back to UnmarshalBytes.\n", g.typeName())
    76  		g.emit("buf := cc.CopyScratchBuffer(%s.SizeBytes()) // escapes: okay.\n", g.r)
    77  		g.emit("length, err := cc.CopyInBytes(addr, buf) // escapes: okay.\n")
    78  		g.emit("// Unmarshal unconditionally. If we had a short copy-in, this results in a\n")
    79  		g.emit("// partially unmarshalled struct.\n")
    80  		g.emit("%s.UnmarshalBytes(buf) // escapes: fallback.\n", g.r)
    81  		g.emit("return length, err\n")
    82  	})
    83  	g.emit("}\n\n")
    84  
    85  	g.emit("// WriteTo implements io.WriterTo.WriteTo.\n")
    86  	g.recordUsedImport("io")
    87  	g.emit("func (%s *%s) WriteTo(writer io.Writer) (int64, error) {\n", g.r, g.typeName())
    88  	g.inIndent(func() {
    89  		g.emit("// Type %s doesn't have a packed layout in memory, fall back to MarshalBytes.\n", g.typeName())
    90  		g.emit("buf := make([]byte, %s.SizeBytes())\n", g.r)
    91  		g.emit("%s.MarshalBytes(buf)\n", g.r)
    92  		g.emit("length, err := writer.Write(buf)\n")
    93  		g.emit("return int64(length), err\n")
    94  	})
    95  	g.emit("}\n\n")
    96  }