// Reads a single arbitrary type and returns the proper StateValue. func readField(val reflect.Value) *protocol.StateValue { msg := &protocol.StateValue{} switch f := val.(type) { case *reflect.BoolValue: msg.Type = protocol.NewStateValue_Type(protocol.StateValue_BOOL) msg.BoolVal = proto.Bool(f.Get()) case *reflect.IntValue: msg.Type = protocol.NewStateValue_Type(protocol.StateValue_INT) msg.IntVal = proto.Int(int(f.Get())) case *reflect.FloatValue: msg.Type = protocol.NewStateValue_Type(protocol.StateValue_FLOAT) msg.FloatVal = proto.Float32(float32(f.Get())) case *reflect.StringValue: msg.Type = protocol.NewStateValue_Type(protocol.StateValue_STRING) msg.StringVal = proto.String(f.Get()) case *reflect.SliceValue: msg.Type = protocol.NewStateValue_Type(protocol.StateValue_ARRAY) msg.ArrayVal = makeStateValueArray(f, f.Len()) case *reflect.StructValue: msg = readStructField(f) case *reflect.PtrValue: return readField(reflect.Indirect(f)) // Dereference and recurse default: panic("State value not supported: " + val.Type().String()) } return msg }
func TestV3FieldState(t *testing.T) { vec := s3dm.V3{9, 9, 9} state := v3FieldState{vec} sv := &protocol.StateValue{} sv.Type = protocol.NewStateValue_Type(protocol.StateValue_VECTOR3) sv.Vector3Val = &protocol.Vector3{&vec.X, &vec.Y, &vec.Z, nil} equalOrError(t, sv, packState(state)) }
func TestPtrFieldState(t *testing.T) { num := 9 state := ptrFieldState{&num} sv := &protocol.StateValue{} sv.Type = protocol.NewStateValue_Type(protocol.StateValue_INT) sv.IntVal = proto.Int(*state.Value) equalOrError(t, sv, packState(state)) }
func TestSingleFieldState(t *testing.T) { // testState is made available by observer_test.go state := testState{9} sv := &protocol.StateValue{} sv.Type = protocol.NewStateValue_Type(protocol.StateValue_INT) sv.IntVal = proto.Int(state.Value) equalOrError(t, sv, packState(state)) }
func TestMultipleFieldState(t *testing.T) { a, b := 1, 2 state := multipleFieldState{a, b} sv := &protocol.StateValue{} sv.Type = protocol.NewStateValue_Type(protocol.StateValue_ARRAY) inner_v1 := makeIntValMsg(a) inner_v2 := makeIntValMsg(b) sv.ArrayVal = append([]*protocol.StateValue{}, inner_v1, inner_v2) equalOrError(t, sv, packState(state)) }
// Makes a Vector3 StateValue. Panics if the StructValue fields do not match the vector. func makeVector3(v *reflect.StructValue) *protocol.StateValue { // If we panic here, struct layout was not as expected x := v.FieldByName("X").(*reflect.FloatValue).Get() y := v.FieldByName("Y").(*reflect.FloatValue).Get() z := v.FieldByName("Z").(*reflect.FloatValue).Get() vector3 := &protocol.Vector3{&x, &y, &z, nil} sv := &protocol.StateValue{ Type: protocol.NewStateValue_Type(protocol.StateValue_VECTOR3), Vector3Val: vector3, } return sv }
func TestSliceFieldState(t *testing.T) { s := []int{1, 2, 3, 4, 5} state := sliceFieldState{s} sv := &protocol.StateValue{} sv.Type = protocol.NewStateValue_Type(protocol.StateValue_ARRAY) msgs := make([]*protocol.StateValue, 0, len(s)) for _, i := range s { msgs = append(msgs, makeIntValMsg(i)) } sv.ArrayVal = msgs equalOrError(t, sv, packState(state)) }
// Creates the right type of StateValue message for an arbitrary State type. func packState(state State) (msg *protocol.StateValue) { val := reflect.NewValue(state) state_v, ok := val.(*reflect.StructValue) if !ok { panic("State is non-struct type!") } field_num := state_v.NumField() if field_num > 1 { // If we have multiple fields, treat as array msg = &protocol.StateValue{} msg.Type = protocol.NewStateValue_Type(protocol.StateValue_ARRAY) msg.ArrayVal = makeStateValueArray(state_v, field_num) } else { // Single field msg = readField(state_v.Field(0)) } return msg }
// Returns a StateValue with IntVal set to the passed value x func makeIntValMsg(x int) *protocol.StateValue { sv := &protocol.StateValue{} sv.Type = protocol.NewStateValue_Type(protocol.StateValue_INT) sv.IntVal = proto.Int(x) return sv }