gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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) []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("return %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) []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("return %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.recordUsedImport("marshal")
    61  	g.recordUsedImport("hostarch")
    62  	g.emit("func (%s *%s) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {\n", g.r, g.typeName())
    63  	g.inIndent(func() {
    64  		g.emit("return %s.CopyOutN(cc, addr, %s.SizeBytes())\n", g.r, g.r)
    65  	})
    66  	g.emit("}\n\n")
    67  
    68  	g.emit("// CopyInN implements marshal.Marshallable.CopyInN.\n")
    69  	g.emit("//go:nosplit\n")
    70  	g.recordUsedImport("marshal")
    71  	g.recordUsedImport("hostarch")
    72  	g.emit("func (%s *%s) CopyInN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {\n", g.r, g.typeName())
    73  	g.inIndent(func() {
    74  		g.emit("// Type %s doesn't have a packed layout in memory, fall back to UnmarshalBytes.\n", g.typeName())
    75  		g.emit("buf := cc.CopyScratchBuffer(%s.SizeBytes()) // escapes: okay.\n", g.r)
    76  		g.emit("length, err := cc.CopyInBytes(addr, buf) // escapes: okay.\n")
    77  		g.emit("// Unmarshal unconditionally. If we had a short copy-in, this results in a\n")
    78  		g.emit("// partially unmarshalled struct.\n")
    79  		g.emit("%s.UnmarshalBytes(buf) // escapes: fallback.\n", g.r)
    80  		g.emit("return length, err\n")
    81  	})
    82  	g.emit("}\n\n")
    83  
    84  	g.emit("// CopyIn implements marshal.Marshallable.CopyIn.\n")
    85  	g.recordUsedImport("marshal")
    86  	g.recordUsedImport("hostarch")
    87  	g.emit("func (%s *%s) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {\n", g.r, g.typeName())
    88  	g.inIndent(func() {
    89  		g.emit("return %s.CopyInN(cc, addr, %s.SizeBytes())\n", g.r, g.r)
    90  	})
    91  	g.emit("}\n\n")
    92  
    93  	g.emit("// WriteTo implements io.WriterTo.WriteTo.\n")
    94  	g.recordUsedImport("io")
    95  	g.emit("func (%s *%s) WriteTo(writer io.Writer) (int64, error) {\n", g.r, g.typeName())
    96  	g.inIndent(func() {
    97  		g.emit("// Type %s doesn't have a packed layout in memory, fall back to MarshalBytes.\n", g.typeName())
    98  		g.emit("buf := make([]byte, %s.SizeBytes())\n", g.r)
    99  		g.emit("%s.MarshalBytes(buf)\n", g.r)
   100  		g.emit("length, err := writer.Write(buf)\n")
   101  		g.emit("return int64(length), err\n")
   102  	})
   103  	g.emit("}\n\n")
   104  }