cstruct_example_test.go 2.1 KB

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