Skip to content

Commit

Permalink
Merge pull request go-restruct#29 from go-restruct/boolean-support
Browse files Browse the repository at this point in the history
Implement boolean support.
  • Loading branch information
jchv authored Mar 23, 2019
2 parents fd0a8d7 + f3f9cc5 commit 13d1f24
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 112 deletions.
74 changes: 50 additions & 24 deletions decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,32 @@ func (d *decoder) unpacker(v reflect.Value) (Unpacker, bool) {
return nil, false
}

func (d *decoder) setUint(f field, v reflect.Value, x uint64) {
switch v.Kind() {
case reflect.Bool:
b := x != 0
if f.Flags&InvertedBoolFlag == InvertedBoolFlag {
b = !b
}
v.SetBool(b)
default:
v.SetUint(x)
}
}

func (d *decoder) setInt(f field, v reflect.Value, x int64) {
switch v.Kind() {
case reflect.Bool:
b := x != 0
if f.Flags&InvertedBoolFlag == InvertedBoolFlag {
b = !b
}
v.SetBool(b)
default:
v.SetInt(x)
}
}

func (d *decoder) read(f field, v reflect.Value) {
if f.Name != "_" {
if s, ok := d.unpacker(v); ok {
Expand Down Expand Up @@ -174,16 +200,16 @@ func (d *decoder) read(f field, v reflect.Value) {
d.skipn(f.Skip)
}

switch f.Type.Kind() {
switch f.BinaryType.Kind() {
case reflect.Array:
l := f.Type.Len()
l := f.BinaryType.Len()

// If the underlying value is a slice, initialize it.
if f.DefType.Kind() == reflect.Slice {
v.Set(reflect.MakeSlice(reflect.SliceOf(f.Type.Elem()), l, l))
if f.NativeType.Kind() == reflect.Slice {
v.Set(reflect.MakeSlice(reflect.SliceOf(f.BinaryType.Elem()), l, l))
}

switch f.DefType.Kind() {
switch f.NativeType.Kind() {
case reflect.String:
// When using strings, treat as C string.
str := string(d.readn(f.SizeOf(v)))
Expand All @@ -198,12 +224,12 @@ func (d *decoder) read(f field, v reflect.Value) {
d.read(ef, v.Index(i))
}
default:
panic(fmt.Errorf("invalid array cast type: %s", f.DefType.String()))
panic(fmt.Errorf("invalid array cast type: %s", f.NativeType.String()))
}

case reflect.Struct:
d.struc = v
d.sfields = cachedFieldsFromStruct(f.Type)
d.sfields = cachedFieldsFromStruct(f.BinaryType)
l := len(d.sfields)
for i := 0; i < l; i++ {
f := d.sfields[i]
Expand All @@ -218,12 +244,12 @@ func (d *decoder) read(f field, v reflect.Value) {
d.struc = struc

case reflect.Slice, reflect.String:
switch f.DefType.Kind() {
switch f.NativeType.Kind() {
case reflect.String:
l := v.Len()
v.SetString(string(d.readn(l)))
case reflect.Slice, reflect.Array:
switch f.DefType.Elem().Kind() {
switch f.NativeType.Elem().Kind() {
case reflect.Uint8:
v.SetBytes(d.readn(f.SizeOf(v)))
default:
Expand All @@ -234,26 +260,26 @@ func (d *decoder) read(f field, v reflect.Value) {
}
}
default:
panic(fmt.Errorf("invalid array cast type: %s", f.DefType.String()))
panic(fmt.Errorf("invalid array cast type: %s", f.NativeType.String()))
}

case reflect.Int8:
v.SetInt(int64(d.readS8(f)))
d.setInt(f, v, int64(d.readS8(f)))
case reflect.Int16:
v.SetInt(int64(d.readS16(f)))
d.setInt(f, v, int64(d.readS16(f)))
case reflect.Int32:
v.SetInt(int64(d.readS32(f)))
d.setInt(f, v, int64(d.readS32(f)))
case reflect.Int64:
v.SetInt(d.readS64(f))
d.setInt(f, v, d.readS64(f))

case reflect.Uint8:
v.SetUint(uint64(d.read8(f)))
case reflect.Uint8, reflect.Bool:
d.setUint(f, v, uint64(d.read8(f)))
case reflect.Uint16:
v.SetUint(uint64(d.read16(f)))
d.setUint(f, v, uint64(d.read16(f)))
case reflect.Uint32:
v.SetUint(uint64(d.read32(f)))
d.setUint(f, v, uint64(d.read32(f)))
case reflect.Uint64:
v.SetUint(d.read64(f))
d.setUint(f, v, d.read64(f))

case reflect.Float32:
v.SetFloat(float64(math.Float32frombits(d.read32(f))))
Expand Down Expand Up @@ -284,25 +310,25 @@ func (d *decoder) read(f field, v reflect.Value) {
sl := 0

// Must use different codepath for signed/unsigned.
switch f.Type.Kind() {
switch f.BinaryType.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
sl = int(v.Int())
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
sl = int(v.Uint())
default:
panic(fmt.Errorf("unsupported sizeof type %s: %s", f.Type.String(), f.Name))
panic(fmt.Errorf("unsupported sizeof type %s: %s", f.BinaryType.String(), f.Name))
}

// Strings are immutable, but we make a blank one so that we can
// figure out the size later. It might be better to do something
// more hackish, like writing the length into the string...
switch sf.DefType.Kind() {
switch sf.NativeType.Kind() {
case reflect.Slice:
sv.Set(reflect.MakeSlice(sf.Type, sl, sl))
sv.Set(reflect.MakeSlice(sf.BinaryType, sl, sl))
case reflect.String:
sv.SetString(string(make([]byte, sl)))
default:
panic(fmt.Errorf("unsupported sizeof target %s", sf.DefType.String()))
panic(fmt.Errorf("unsupported sizeof target %s", sf.NativeType.String()))
}
}
}
Expand Down
74 changes: 56 additions & 18 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,44 @@ func (e *encoder) packer(v reflect.Value) (Packer, bool) {
return nil, false
}

func (e *encoder) intFromField(f field, v reflect.Value) int64 {
switch v.Kind() {
case reflect.Bool:
b := v.Bool()
if f.Flags&InvertedBoolFlag == InvertedBoolFlag {
b = !b
}
if b {
if f.Flags&VariantBoolFlag == VariantBoolFlag {
return -1
}
return 1
}
return 0
default:
return v.Int()
}
}

func (e *encoder) uintFromField(f field, v reflect.Value) uint64 {
switch v.Kind() {
case reflect.Bool:
b := v.Bool()
if f.Flags&InvertedBoolFlag == InvertedBoolFlag {
b = !b
}
if b {
if f.Flags&VariantBoolFlag == VariantBoolFlag {
return ^uint64(0)
}
return 1
}
return 0
default:
return v.Uint()
}
}

func (e *encoder) write(f field, v reflect.Value) {
if f.Name != "_" {
if s, ok := e.packer(v); ok {
Expand Down Expand Up @@ -219,39 +257,39 @@ func (e *encoder) write(f field, v reflect.Value) {
if f.SIndex != -1 {
sv := struc.Field(f.SIndex)

switch f.Type.Kind() {
switch f.BinaryType.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v.SetInt(int64(sv.Len()))
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v.SetUint(uint64(sv.Len()))
default:
panic(fmt.Errorf("unsupported sizeof type %s: %s", f.Type.String(), f.Name))
panic(fmt.Errorf("unsupported sizeof type %s: %s", f.BinaryType.String(), f.Name))
}
}

switch f.Type.Kind() {
switch f.BinaryType.Kind() {
case reflect.Array, reflect.Slice, reflect.String:
switch f.DefType.Kind() {
switch f.NativeType.Kind() {
case reflect.Array, reflect.Slice, reflect.String:
ef := f.Elem()
len := v.Len()
cap := len
if f.Type.Kind() == reflect.Array {
cap = f.Type.Len()
if f.BinaryType.Kind() == reflect.Array {
cap = f.BinaryType.Len()
}
for i := 0; i < len; i++ {
e.write(ef, v.Index(i))
}
for i := len; i < cap; i++ {
e.write(ef, reflect.New(f.Type.Elem()).Elem())
e.write(ef, reflect.New(f.BinaryType.Elem()).Elem())
}
default:
panic(fmt.Errorf("invalid array cast type: %s", f.DefType.String()))
panic(fmt.Errorf("invalid array cast type: %s", f.NativeType.String()))
}

case reflect.Struct:
e.struc = v
e.sfields = cachedFieldsFromStruct(f.Type)
e.sfields = cachedFieldsFromStruct(f.BinaryType)
l := len(e.sfields)
for i := 0; i < l; i++ {
sf := e.sfields[i]
Expand All @@ -266,22 +304,22 @@ func (e *encoder) write(f field, v reflect.Value) {
e.struc = struc

case reflect.Int8:
e.writeS8(f, int8(v.Int()))
e.writeS8(f, int8(e.intFromField(f, v)))
case reflect.Int16:
e.writeS16(f, int16(v.Int()))
e.writeS16(f, int16(e.intFromField(f, v)))
case reflect.Int32:
e.writeS32(f, int32(v.Int()))
e.writeS32(f, int32(e.intFromField(f, v)))
case reflect.Int64:
e.writeS64(f, int64(v.Int()))
e.writeS64(f, int64(e.intFromField(f, v)))

case reflect.Uint8:
e.write8(f, uint8(v.Uint()))
case reflect.Uint8, reflect.Bool:
e.write8(f, uint8(e.uintFromField(f, v)))
case reflect.Uint16:
e.write16(f, uint16(v.Uint()))
e.write16(f, uint16(e.uintFromField(f, v)))
case reflect.Uint32:
e.write32(f, uint32(v.Uint()))
e.write32(f, uint32(e.uintFromField(f, v)))
case reflect.Uint64:
e.write64(f, uint64(v.Uint()))
e.write64(f, uint64(e.uintFromField(f, v)))

case reflect.Float32:
e.write32(f, math.Float32bits(float32(v.Float())))
Expand Down
Loading

0 comments on commit 13d1f24

Please sign in to comment.