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:
46
storer.go
46
storer.go
@@ -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")
|
||||
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user