Skip to content

Commit 25c8824

Browse files
committed
Handle arbitrary interfaces. Closes #27.
1 parent 643e53f commit 25c8824

File tree

2 files changed

+39
-17
lines changed

2 files changed

+39
-17
lines changed

decoder.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,7 @@ func (d *decoder) sizeFromCtrlByte(ctrlByte byte, offset uint, typeNum dataType)
8484
}
8585

8686
func (d *decoder) decodeFromType(dtype dataType, size uint, offset uint, result reflect.Value) (uint, error) {
87-
for result.Kind() == reflect.Ptr {
88-
if result.IsNil() {
89-
result.Set(reflect.New(result.Type().Elem()))
90-
}
91-
result = result.Elem()
92-
}
87+
result = d.indirect(result)
9388

9489
switch dtype {
9590
case _Bool:
@@ -143,6 +138,23 @@ func (d *decoder) unmarshalBool(size uint, offset uint, result reflect.Value) (u
143138
}
144139
}
145140

141+
// follow pointers and create values as necessary
142+
func (d *decoder) indirect(result reflect.Value) reflect.Value {
143+
for {
144+
if result.Kind() == reflect.Ptr {
145+
if result.IsNil() {
146+
result.Set(reflect.New(result.Type().Elem()))
147+
}
148+
result = result.Elem()
149+
} else if result.Kind() == reflect.Interface && !result.IsNil() {
150+
result = result.Elem()
151+
} else {
152+
break
153+
}
154+
}
155+
return result
156+
}
157+
146158
func (d *decoder) unmarshalBytes(size uint, offset uint, result reflect.Value) (uint, error) {
147159
value, newOffset, err := d.decodeBytes(size, offset)
148160
if err != nil {
@@ -238,6 +250,7 @@ func (d *decoder) unmarshalInt32(size uint, offset uint, result reflect.Value) (
238250
}
239251

240252
func (d *decoder) unmarshalMap(size uint, offset uint, result reflect.Value) (uint, error) {
253+
result = d.indirect(result)
241254
switch result.Kind() {
242255
default:
243256
return 0, newUnmarshalTypeError("map", result.Type())
@@ -250,17 +263,6 @@ func (d *decoder) unmarshalMap(size uint, offset uint, result reflect.Value) (ui
250263
newOffset, err := d.decodeMap(size, offset, rv)
251264
result.Set(rv)
252265
return newOffset, err
253-
case reflect.Ptr:
254-
// XXX - This duplicate Ptr hanlding code exists because decodeMap
255-
// calls unmarshalMap directly when handling embedded structs. It
256-
// would be nice to clean this up.
257-
for result.Kind() == reflect.Ptr {
258-
if result.IsNil() {
259-
result.Set(reflect.New(result.Type().Elem()))
260-
}
261-
result = result.Elem()
262-
}
263-
return d.unmarshalMap(size, offset, result)
264266
}
265267
}
266268

reader_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,26 @@ func (s *MySuite) TestDecoder(c *C) {
162162
c.Assert(reader.Close(), IsNil)
163163
}
164164

165+
type TestInterface interface {
166+
method() bool
167+
}
168+
169+
func (t *TestType) method() bool {
170+
return t.Boolean
171+
}
172+
173+
func (s *MySuite) TestStructInterface(c *C) {
174+
var result TestInterface = &TestType{}
175+
176+
reader, err := Open("test-data/test-data/MaxMind-DB-test-decoder.mmdb")
177+
c.Assert(err, IsNil)
178+
179+
c.Assert(reader.Lookup(net.ParseIP("::1.1.1.0"), &result), IsNil)
180+
181+
c.Assert(result.method(), Equals, true)
182+
183+
}
184+
165185
type NestedMapX struct {
166186
UTF8StringX string `maxminddb:"utf8_stringX"`
167187
}

0 commit comments

Comments
 (0)