diff options
author | Rastislav Szabo <raszabo@cisco.com> | 2017-05-04 11:09:03 +0200 |
---|---|---|
committer | Rastislav Szabo <raszabo@cisco.com> | 2017-05-04 11:12:35 +0200 |
commit | a101d966133a70b8a76526be25070436d14fcf9f (patch) | |
tree | 75e2dbf20de615e58252b780b2ba5baae8fdcf82 /vendor/github.com/lunixbochs/struc/struc.go | |
parent | a968ead74525125dff9ae90b1c9a9102e4327900 (diff) |
initial commit
Signed-off-by: Rastislav Szabo <raszabo@cisco.com>
Diffstat (limited to 'vendor/github.com/lunixbochs/struc/struc.go')
-rw-r--r-- | vendor/github.com/lunixbochs/struc/struc.go | 117 |
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 +} |