summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/lunixbochs/struc/field.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/lunixbochs/struc/field.go')
-rw-r--r--vendor/github.com/lunixbochs/struc/field.go288
1 files changed, 0 insertions, 288 deletions
diff --git a/vendor/github.com/lunixbochs/struc/field.go b/vendor/github.com/lunixbochs/struc/field.go
deleted file mode 100644
index 6e59c2a..0000000
--- a/vendor/github.com/lunixbochs/struc/field.go
+++ /dev/null
@@ -1,288 +0,0 @@
-package struc
-
-import (
- "bytes"
- "encoding/binary"
- "fmt"
- "math"
- "reflect"
-)
-
-type Field struct {
- Name string
- Ptr bool
- Index int
- Type Type
- defType Type
- Array bool
- Slice bool
- Len int
- Order binary.ByteOrder
- Sizeof []int
- Sizefrom []int
- Fields Fields
- kind reflect.Kind
-}
-
-func (f *Field) String() string {
- var out string
- if f.Type == Pad {
- return fmt.Sprintf("{type: Pad, len: %d}", f.Len)
- } else {
- out = fmt.Sprintf("type: %s, order: %v", f.Type.String(), f.Order)
- }
- if f.Sizefrom != nil {
- out += fmt.Sprintf(", sizefrom: %v", f.Sizefrom)
- } else if f.Len > 0 {
- out += fmt.Sprintf(", len: %d", f.Len)
- }
- if f.Sizeof != nil {
- out += fmt.Sprintf(", sizeof: %v", f.Sizeof)
- }
- return "{" + out + "}"
-}
-
-func (f *Field) Size(val reflect.Value, options *Options) int {
- typ := f.Type.Resolve(options)
- size := 0
- if typ == Struct {
- vals := []reflect.Value{val}
- if f.Slice {
- vals = make([]reflect.Value, val.Len())
- for i := 0; i < val.Len(); i++ {
- vals[i] = val.Index(i)
- }
- }
- for _, val := range vals {
- size += f.Fields.Sizeof(val, options)
- }
- } else if typ == Pad {
- size = f.Len
- } else if f.Slice || f.kind == reflect.String {
- length := val.Len()
- if f.Len > 1 {
- length = f.Len
- }
- size = length * typ.Size()
- } else if typ == CustomType {
- return val.Addr().Interface().(Custom).Size(options)
- } else {
- size = typ.Size()
- }
- align := options.ByteAlign
- if align > 0 && size < align {
- size = align
- }
- return size
-}
-
-func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) {
- order := f.Order
- if options.Order != nil {
- order = options.Order
- }
- if f.Ptr {
- val = val.Elem()
- }
- typ := f.Type.Resolve(options)
- switch typ {
- case Struct:
- return f.Fields.Pack(buf, val, options)
- case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
- size = typ.Size()
- var n uint64
- switch f.kind {
- case reflect.Bool:
- if val.Bool() {
- n = 1
- } else {
- n = 0
- }
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- n = uint64(val.Int())
- default:
- n = val.Uint()
- }
- switch typ {
- case Bool:
- if n != 0 {
- buf[0] = 1
- } else {
- buf[0] = 0
- }
- case Int8, Uint8:
- buf[0] = byte(n)
- case Int16, Uint16:
- order.PutUint16(buf, uint16(n))
- case Int32, Uint32:
- order.PutUint32(buf, uint32(n))
- case Int64, Uint64:
- order.PutUint64(buf, uint64(n))
- }
- case Float32, Float64:
- size = typ.Size()
- n := val.Float()
- switch typ {
- case Float32:
- order.PutUint32(buf, math.Float32bits(float32(n)))
- case Float64:
- order.PutUint64(buf, math.Float64bits(n))
- }
- case String:
- switch f.kind {
- case reflect.String:
- size = val.Len()
- copy(buf, []byte(val.String()))
- default:
- // TODO: handle kind != bytes here
- size = val.Len()
- copy(buf, val.Bytes())
- }
- case CustomType:
- return val.Addr().Interface().(Custom).Pack(buf, options)
- default:
- panic(fmt.Sprintf("no pack handler for type: %s", typ))
- }
- return
-}
-
-func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) {
- typ := f.Type.Resolve(options)
- if typ == Pad {
- for i := 0; i < length; i++ {
- buf[i] = 0
- }
- return length, nil
- }
- if f.Slice {
- // special case strings and byte slices for performance
- end := val.Len()
- if !f.Array && typ == Uint8 && (f.defType == Uint8 || f.kind == reflect.String) {
- var tmp []byte
- if f.kind == reflect.String {
- tmp = []byte(val.String())
- } else {
- tmp = val.Bytes()
- }
- copy(buf, tmp)
- if end < length {
- // TODO: allow configuring pad byte?
- rep := bytes.Repeat([]byte{0}, length-end)
- copy(buf[end:], rep)
- return length, nil
- }
- return val.Len(), nil
- }
- pos := 0
- var zero reflect.Value
- if end < length {
- zero = reflect.Zero(val.Type().Elem())
- }
- for i := 0; i < length; i++ {
- cur := zero
- if i < end {
- cur = val.Index(i)
- }
- if n, err := f.packVal(buf[pos:], cur, 1, options); err != nil {
- return pos, err
- } else {
- pos += n
- }
- }
- return pos, nil
- } else {
- return f.packVal(buf, val, length, options)
- }
-}
-
-func (f *Field) unpackVal(buf []byte, val reflect.Value, length int, options *Options) error {
- order := f.Order
- if options.Order != nil {
- order = options.Order
- }
- if f.Ptr {
- val = val.Elem()
- }
- typ := f.Type.Resolve(options)
- switch typ {
- case Float32, Float64:
- var n float64
- switch typ {
- case Float32:
- n = float64(math.Float32frombits(order.Uint32(buf)))
- case Float64:
- n = math.Float64frombits(order.Uint64(buf))
- }
- switch f.kind {
- case reflect.Float32, reflect.Float64:
- val.SetFloat(n)
- default:
- return fmt.Errorf("struc: refusing to unpack float into field %s of type %s", f.Name, f.kind.String())
- }
- case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
- var n uint64
- switch typ {
- case Int8:
- n = uint64(int64(int8(buf[0])))
- case Int16:
- n = uint64(int64(int16(order.Uint16(buf))))
- case Int32:
- n = uint64(int64(int32(order.Uint32(buf))))
- case Int64:
- n = uint64(int64(order.Uint64(buf)))
- case Bool, Uint8:
- n = uint64(buf[0])
- case Uint16:
- n = uint64(order.Uint16(buf))
- case Uint32:
- n = uint64(order.Uint32(buf))
- case Uint64:
- n = uint64(order.Uint64(buf))
- }
- switch f.kind {
- case reflect.Bool:
- val.SetBool(n != 0)
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- val.SetInt(int64(n))
- default:
- val.SetUint(n)
- }
- default:
- panic(fmt.Sprintf("no unpack handler for type: %s", typ))
- }
- return nil
-}
-
-func (f *Field) Unpack(buf []byte, val reflect.Value, length int, options *Options) error {
- typ := f.Type.Resolve(options)
- if typ == Pad || f.kind == reflect.String {
- if typ == Pad {
- return nil
- } else {
- val.SetString(string(buf))
- return nil
- }
- } else if f.Slice {
- if val.Cap() < length {
- val.Set(reflect.MakeSlice(val.Type(), length, length))
- } else if val.Len() < length {
- val.Set(val.Slice(0, length))
- }
- // special case byte slices for performance
- if !f.Array && typ == Uint8 && f.defType == Uint8 {
- copy(val.Bytes(), buf[:length])
- return nil
- }
- pos := 0
- size := typ.Size()
- for i := 0; i < length; i++ {
- if err := f.unpackVal(buf[pos:pos+size], val.Index(i), 1, options); err != nil {
- return err
- }
- pos += size
- }
- return nil
- } else {
- return f.unpackVal(buf, val, length, options)
- }
-}