diff --git a/gluamapper.go b/gluamapper.go index f23cc66..51b7f25 100644 --- a/gluamapper.go +++ b/gluamapper.go @@ -4,10 +4,11 @@ package gluamapper import ( "errors" "fmt" - "github.com/mitchellh/mapstructure" - "github.com/yuin/gopher-lua" "regexp" "strings" + + "github.com/mitchellh/mapstructure" + "github.com/yuin/gopher-lua" ) // Option is a configuration that is used to create a new mapper. @@ -18,8 +19,12 @@ type Option struct { // Returns error if unused keys exist. ErrorUnused bool - // A struct tag name for lua table keys . This defaults to "gluamapper" + // A struct tag name for lua table keys. This defaults to "gluamapper" TagName string + + // Metadata contains information about decoding a structure that + // is tedious or difficult to get otherwise. + Metadata *mapstructure.Metadata } // Mapper maps a lua table to a Go struct pointer. @@ -50,6 +55,7 @@ func (mapper *Mapper) Map(tbl *lua.LTable, st interface{}) error { Result: st, TagName: opt.TagName, ErrorUnused: opt.ErrorUnused, + Metadata: opt.Metadata, } decoder, err := mapstructure.NewDecoder(config) if err != nil { @@ -63,13 +69,13 @@ func Map(tbl *lua.LTable, st interface{}) error { return NewMapper(Option{}).Map(tbl, st) } - // Id is an Option.NameFunc that returns given string as-is. func Id(s string) string { return s } var camelre = regexp.MustCompile(`_([a-z])`) + // ToUpperCamelCase is an Option.NameFunc that converts strings from snake case to upper camel case. func ToUpperCamelCase(s string) string { return strings.ToUpper(string(s[0])) + camelre.ReplaceAllStringFunc(s[1:len(s)], func(s string) string { return strings.ToUpper(s[1:len(s)]) }) diff --git a/gluamapper_test.go b/gluamapper_test.go index 265f5e5..4ad67e0 100644 --- a/gluamapper_test.go +++ b/gluamapper_test.go @@ -1,10 +1,12 @@ package gluamapper import ( - "github.com/yuin/gopher-lua" "path/filepath" "runtime" "testing" + + "github.com/mitchellh/mapstructure" + "github.com/yuin/gopher-lua" ) func errorIfNotEqual(t *testing.T, v1, v2 interface{}) { @@ -137,3 +139,40 @@ func TestError(t *testing.T) { t.Error("invalid error message") } } + +func TestUnused(t *testing.T) { + L := lua.NewState() + defer L.Close() + if err := L.DoString(` + person = { + name = "Michel", + age = "31", -- weakly input + work_place = "San Jose", + role = { + { + name = "Administrator" + }, + { + name = "Operator" + } + }, + foo = "unused key foo", + bar = "unused key bar" + } + `); err != nil { + t.Error(err) + } + var person testPerson + + var metadata mapstructure.Metadata + opts := Option{ + Metadata: &metadata, + } + mapper := NewMapper(opts) + if err := mapper.Map(L.GetGlobal("person").(*lua.LTable), &person); err != nil { + t.Error(err) + } + + errorIfNotEqual(t, "Foo", metadata.Unused[0]) + errorIfNotEqual(t, "Bar", metadata.Unused[1]) +}