aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/lunixbochs/struc/struc.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/lunixbochs/struc/struc.go')
-rw-r--r--vendor/github.com/lunixbochs/struc/struc.go117
1 files changed, 117 insertions, 0 deletions
diff --git a/vendor/github.com/lunixbochs/struc/struc.go b/vendor/github.com/lunixbochs/struc/struc.go
new file mode 100644
index 0000000..3d85fe3
--- /dev/null
+++ b/vendor/github.com/lunixbochs/struc/struc.go
@@ -0,0 +1,117 @@
+package struc
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "reflect"
+)
+
+type Options struct {
+ ByteAlign int
+ PtrSize int
+ Order binary.ByteOrder
+}
+
+func (o *Options) Validate() error {
+ if o.PtrSize == 0 {
+ o.PtrSize = 32
+ } else {
+ switch o.PtrSize {
+ case 8, 16, 32, 64:
+ default:
+ return fmt.Errorf("Invalid Options.PtrSize: %d. Must be in (8, 16, 32, 64)", o.PtrSize)
+ }
+ }
+ return nil
+}
+
+var emptyOptions = &Options{}
+
+func prep(data interface{}) (reflect.Value, Packer, error) {
+ value := reflect.ValueOf(data)
+ for value.Kind() == reflect.Ptr {
+ next := value.Elem().Kind()
+ if next == reflect.Struct || next == reflect.Ptr {
+ value = value.Elem()
+ } else {
+ break
+ }
+ }
+ switch value.Kind() {
+ case reflect.Struct:
+ fields, err := parseFields(value)
+ return value, fields, err
+ default:
+ if !value.IsValid() {
+ return reflect.Value{}, nil, fmt.Errorf("Invalid reflect.Value for %+v", data)
+ }
+ if c, ok := data.(Custom); ok {
+ return value, customFallback{c}, nil
+ }
+ return value, binaryFallback(value), nil
+ }
+}
+
+func Pack(w io.Writer, data interface{}) error {
+ return PackWithOptions(w, data, nil)
+}
+
+func PackWithOptions(w io.Writer, data interface{}, options *Options) error {
+ if options == nil {
+ options = emptyOptions
+ }
+ if err := options.Validate(); err != nil {
+ return err
+ }
+ val, packer, err := prep(data)
+ if err != nil {
+ return err
+ }
+ if val.Type().Kind() == reflect.String {
+ val = val.Convert(reflect.TypeOf([]byte{}))
+ }
+ size := packer.Sizeof(val, options)
+ buf := make([]byte, size)
+ if _, err := packer.Pack(buf, val, options); err != nil {
+ return err
+ }
+ _, err = w.Write(buf)
+ return err
+}
+
+func Unpack(r io.Reader, data interface{}) error {
+ return UnpackWithOptions(r, data, nil)
+}
+
+func UnpackWithOptions(r io.Reader, data interface{}, options *Options) error {
+ if options == nil {
+ options = emptyOptions
+ }
+ if err := options.Validate(); err != nil {
+ return err
+ }
+ val, packer, err := prep(data)
+ if err != nil {
+ return err
+ }
+ return packer.Unpack(r, val, options)
+}
+
+func Sizeof(data interface{}) (int, error) {
+ return SizeofWithOptions(data, nil)
+}
+
+func SizeofWithOptions(data interface{}, options *Options) (int, error) {
+ if options == nil {
+ options = emptyOptions
+ }
+ if err := options.Validate(); err != nil {
+ return 0, err
+ }
+ val, packer, err := prep(data)
+ if err != nil {
+ return 0, err
+ }
+ return packer.Sizeof(val, options), nil
+}