// Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause // Only built on 64-bit platforms to avoid complexity //go:build amd64 || arm64 || mips64le || ppc64le || riscv64 package cstruct import "fmt" // This test provides a semi-realistic example of how you can // use this package to decode a C structure. func ExampleDecoder() { // Our example C structure: // struct mystruct { // char *p; // char c; // /* implicit: char _pad[3]; */ // int x; // }; // // The Go structure definition: type myStruct struct { Ptr uintptr Ch byte Intval uint32 } // Our "in-memory" version of the above structure buf := []byte{ 1, 2, 3, 4, 0, 0, 0, 0, // ptr 5, // ch 99, 99, 99, // padding 78, 6, 0, 0, // x } d := NewDecoder(buf) // Decode the structure; if one of these function returns an error, // then subsequent decoder functions will return the zero value. var x myStruct x.Ptr = d.Uintptr() x.Ch = d.Byte() x.Intval = d.Uint32() // Note that per the Go language spec: // [...] when evaluating the operands of an expression, assignment, // or return statement, all function calls, method calls, and // (channel) communication operations are evaluated in lexical // left-to-right order // // Since each field is assigned via a function call, one could use the // following snippet to decode the struct. // x := myStruct{ // Ptr: d.Uintptr(), // Ch: d.Byte(), // Intval: d.Uint32(), // } // // However, this means that reordering the fields in the initialization // statement–normally a semantically identical operation–would change // the way the structure is parsed. Thus we do it as above with // explicit ordering. // After finishing with the decoder, check errors if err := d.Err(); err != nil { panic(err) } // Print the decoder offset and structure fmt.Printf("off=%d struct=%#v\n", d.Offset(), x) // Output: off=16 struct=cstruct.myStruct{Ptr:0x4030201, Ch:0x5, Intval:0x64e} }