cstruct_example_test.go 2.0 KB

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