Skip to content

Instantly share code, notes, and snippets.

@karfield
Last active June 15, 2016 19:44
Show Gist options
  • Save karfield/9f54277fcccef2c1fca6 to your computer and use it in GitHub Desktop.
Save karfield/9f54277fcccef2c1fca6 to your computer and use it in GitHub Desktop.
Golang: reflect mthod from wrapped struct anonymously
package common
import (
"encoding/xml"
"fmt"
"reflect"
"regexp"
"strconv"
)
type XmlDecodeError struct {
msg string
}
func (e *XmlDecodeError) Error() string {
return e.msg
}
func newXmlDecodeError(msg string) error {
e := new(XmlDecodeError)
e.msg = msg
return e
}
type _customXmlTypeInterface interface {
decode(str string) error
}
type _customXmlType struct {
}
func (c *_customXmlType) invokeDecode(str string) error {
decodeMethod := reflect.ValueOf(c).MethodByName("decode")
fmt.Printf("%+v", reflect.ValueOf(c).NumMethod())
results := decodeMethod.Call([]reflect.Value{
reflect.ValueOf(str)})
err, _ := results[0].Interface().(error)
return err
}
func (c *_customXmlType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var v string
d.DecodeElement(&v, &start)
return c.invokeDecode(v)
}
func (c *_customXmlType) UnmarshalXMLAttr(attr xml.Attr) error {
return c.invokeDecode(attr.Value)
}
type XmlFileMode struct {
_customXmlType
mode uint
}
var _FileModeRegex = regexp.MustCompile("0([0-7])([0-7])([0-7])")
func (p *XmlFileMode) decode(value string) error {
ss := _FileModeRegex.FindStringSubmatch(value)
if len(ss) == 0 {
return newXmlDecodeError("illegal file mode/permission: " + value)
}
var mode uint = 0
if n, err := strconv.Atoi(ss[1]); err != nil {
return err
} else {
mode = uint(n)
mode <<= 3
}
if n, err := strconv.Atoi(ss[2]); err != nil {
return err
} else {
mode += uint(n)
mode <<= 3
}
if n, err := strconv.Atoi(ss[3]); err != nil {
return err
} else {
mode += uint(n)
}
p.mode = mode
return nil
}
func (p *XmlFileMode) Value() uint {
return p.mode
}
package common
import (
"encoding/xml"
"testing"
)
func TestXmlFileModeDecode(t *testing.T) {
result := new(struct {
XMLName xml.Name `xml:"root"`
FileMode XmlFileMode `xml:"mode,attr"`
})
data := `
<root mode="0755"/>
`
err := xml.Unmarshal([]byte(data), result)
if err != nil {
t.Error(err)
return
}
if result.FileMode.Value() != 0755 {
t.Error("unmatched decoded value:", result.FileMode.Value())
return
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment