mirror of
https://github.com/volatiletech/authboss.git
synced 2026-06-19 23:00:27 +02:00
Add unbind to pull data from a struct.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DataType represents the various types that clients must be able to store.
|
// DataType represents the various types that clients must be able to store.
|
||||||
@@ -16,6 +17,8 @@ const (
|
|||||||
DateTime
|
DateTime
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var dateTimeType = reflect.TypeOf(time.Time{})
|
||||||
|
|
||||||
func (d DataType) String() string {
|
func (d DataType) String() string {
|
||||||
switch d {
|
switch d {
|
||||||
case Integer:
|
case Integer:
|
||||||
@@ -97,7 +100,7 @@ func (a Attributes) Bind(strct interface{}) error {
|
|||||||
}
|
}
|
||||||
field.SetString(v.Value.(string))
|
field.SetString(v.Value.(string))
|
||||||
case DateTime:
|
case DateTime:
|
||||||
timeType := reflect.TypeOf(time.Time{})
|
timeType := dateTimeType
|
||||||
if fieldType != timeType {
|
if fieldType != timeType {
|
||||||
return fmt.Errorf("Bind: Field %s's type should be %s but was %s", k, timeType.String(), fieldType)
|
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
|
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.
|
// UserNotFound should be returned from Get when the record is not found.
|
||||||
var UserNotFound = errors.New("User 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