cstruct_example_test.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Only built on 64-bit platforms to avoid complexity
  5. //go:build amd64 || arm64 || mips64le || ppc64le || riscv64
  6. // +build amd64 arm64 mips64le ppc64le riscv64
  7. package cstruct
  8. import "fmt"
  9. // This test provides a semi-realistic example of how you can
  10. // use this package to decode a C structure.
  11. func ExampleDecoder() {
  12. // Our example C structure:
  13. // struct mystruct {
  14. // char *p;
  15. // char c;
  16. // /* implicit: char _pad[3]; */
  17. // int x;
  18. // };
  19. //
  20. // The Go structure definition:
  21. type myStruct struct {
  22. Ptr uintptr
  23. Ch byte
  24. Intval uint32
  25. }
  26. // Our "in-memory" version of the above structure
  27. buf := []byte{
  28. 1, 2, 3, 4, 0, 0, 0, 0, // ptr
  29. 5, // ch
  30. 99, 99, 99, // padding
  31. 78, 6, 0, 0, // x
  32. }
  33. d := NewDecoder(buf)
  34. // Decode the structure; if one of these function returns an error,
  35. // then subsequent decoder functions will return the zero value.
  36. var x myStruct
  37. x.Ptr = d.Uintptr()
  38. x.Ch = d.Byte()
  39. x.Intval = d.Uint32()
  40. // Note that per the Go language spec:
  41. // [...] when evaluating the operands of an expression, assignment,
  42. // or return statement, all function calls, method calls, and
  43. // (channel) communication operations are evaluated in lexical
  44. // left-to-right order
  45. //
  46. // Since each field is assigned via a function call, one could use the
  47. // following snippet to decode the struct.
  48. // x := myStruct{
  49. // Ptr: d.Uintptr(),
  50. // Ch: d.Byte(),
  51. // Intval: d.Uint32(),
  52. // }
  53. //
  54. // However, this means that reordering the fields in the initialization
  55. // statement–normally a semantically identical operation–would change
  56. // the way the structure is parsed. Thus we do it as above with
  57. // explicit ordering.
  58. // After finishing with the decoder, check errors
  59. if err := d.Err(); err != nil {
  60. panic(err)
  61. }
  62. // Print the decoder offset and structure
  63. fmt.Printf("off=%d struct=%#v\n", d.Offset(), x)
  64. // Output: off=16 struct=cstruct.myStruct{Ptr:0x4030201, Ch:0x5, Intval:0x64e}
  65. }