1
0
mirror of https://github.com/volatiletech/authboss.git synced 2025-09-16 09:06:20 +02:00

Add unbind to pull data from a struct.

This commit is contained in:
Aaron
2015-01-07 11:39:12 -08:00
parent 92b3172a3e
commit 11a0cabe5f
2 changed files with 93 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"reflect"
"time"
"unicode"
)
// DataType represents the various types that clients must be able to store.
@@ -16,6 +17,8 @@ const (
DateTime
)
var dateTimeType = reflect.TypeOf(time.Time{})
func (d DataType) String() string {
switch d {
case Integer:
@@ -97,7 +100,7 @@ func (a Attributes) Bind(strct interface{}) error {
}
field.SetString(v.Value.(string))
case DateTime:
timeType := reflect.TypeOf(time.Time{})
timeType := dateTimeType
if fieldType != timeType {
return fmt.Errorf("Bind: Field %s's type should be %s but was %s", k, timeType.String(), fieldType)
}
@@ -108,6 +111,47 @@ func (a Attributes) Bind(strct interface{}) error {
return nil
}
// Unbind is the opposite of Bind, taking a struct in and producing a list of attributes.
func Unbind(intf interface{}) Attributes {
structValue := reflect.ValueOf(intf)
if structValue.Kind() == reflect.Ptr {
structValue = structValue.Elem()
}
structType := structValue.Type()
attr := make(Attributes)
for i := 0; i < structValue.NumField(); i++ {
field := structValue.Field(i)
name := structType.Field(i).Name
if unicode.IsLower(rune(name[0])) {
continue // Unexported
}
switch field.Kind() {
case reflect.Struct:
if field.Type() == dateTimeType {
attr[name] = Attribute{
Type: DateTime,
Value: field.Interface(),
}
}
case reflect.Int:
attr[name] = Attribute{
Type: Integer,
Value: field.Interface(),
}
case reflect.String:
attr[name] = Attribute{
Type: String,
Value: field.Interface(),
}
}
}
return attr
}
// UserNotFound should be returned from Get when the record is not found.
var UserNotFound = errors.New("User Not Found")

View File

@@ -104,3 +104,51 @@ func TestAttributes_BindTypeFail(t *testing.T) {
}
}
func TestAttributes_Unbind(t *testing.T) {
s1 := struct {
Integer int
String string
Time time.Time
SomethingElse1 int32
SomethingElse2 *Config
unexported int
}{5, "string", time.Now(), 5, nil, 5}
attr := Unbind(s1)
if len(attr) != 3 {
t.Error("Expected three fields, got:", len(attr))
}
if v, ok := attr["Integer"]; !ok {
t.Error("Could not find Integer entry.")
} else if v.Type != Integer {
t.Error("Described type is wrong:", v.Type)
} else if i, ok := v.Value.(int); !ok {
t.Errorf("Underlying type is wrong: %T", v)
} else if s1.Integer != i {
t.Error("Underlying value is wrong:", i)
}
if v, ok := attr["String"]; !ok {
t.Error("Could not find String entry.")
} else if v.Type != String {
t.Error("Described type is wrong:", v.Type)
} else if s, ok := v.Value.(string); !ok {
t.Errorf("Underlying type is wrong: %T", v)
} else if s1.String != s {
t.Error("Underlying value is wrong:", s)
}
if v, ok := attr["Time"]; !ok {
t.Error("Could not find Time entry.")
} else if v.Type != DateTime {
t.Error("Described type is wrong:", v.Type)
} else if i, ok := v.Value.(time.Time); !ok {
t.Errorf("Underlying type is wrong: %T", v)
} else if s1.Time != i {
t.Error("Underlying value is wrong:", i)
}
}