Skip to content

Commit b8ac5c0

Browse files
authored
Merge pull request #144 from oschwald/v2
v2
2 parents 42e7f85 + cb27d1e commit b8ac5c0

File tree

13 files changed

+699
-541
lines changed

13 files changed

+699
-541
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
name: Build
99
strategy:
1010
matrix:
11-
go-version: [1.21.x, 1.22.x]
11+
go-version: [1.23.0-rc.1]
1212
platform: [ubuntu-latest, macos-latest, windows-latest]
1313
runs-on: ${{ matrix.platform }}
1414
steps:

.golangci.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ disable = [
1818
"forcetypeassert",
1919
"funlen",
2020
"gochecknoglobals",
21+
"gocognit",
2122
"godox",
2223
"gomnd",
2324
"inamedparam",

decoder.go

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ const (
3030
_Slice
3131
// We don't use the next two. They are placeholders. See the spec
3232
// for more details.
33-
_Container //nolint: deadcode, varcheck // above
34-
_Marker //nolint: deadcode, varcheck // above
33+
_Container //nolint:deadcode,varcheck // above
34+
_Marker //nolint:deadcode,varcheck // above
3535
_Bool
3636
_Float32
3737
)
@@ -89,6 +89,82 @@ func (d *decoder) decodeToDeserializer(
8989
return d.decodeFromTypeToDeserializer(typeNum, size, newOffset, dser, depth+1)
9090
}
9191

92+
func (d *decoder) decodePath(
93+
offset uint,
94+
path []any,
95+
result reflect.Value,
96+
) error {
97+
PATH:
98+
for i, v := range path {
99+
var (
100+
typeNum dataType
101+
size uint
102+
err error
103+
)
104+
typeNum, size, offset, err = d.decodeCtrlData(offset)
105+
if err != nil {
106+
return err
107+
}
108+
109+
if typeNum == _Pointer {
110+
pointer, _, err := d.decodePointer(size, offset)
111+
if err != nil {
112+
return err
113+
}
114+
115+
typeNum, size, offset, err = d.decodeCtrlData(pointer)
116+
if err != nil {
117+
return err
118+
}
119+
}
120+
121+
switch v := v.(type) {
122+
case string:
123+
// We are expecting a map
124+
if typeNum != _Map {
125+
// XXX - use type names in errors.
126+
return fmt.Errorf("expected a map for %s but found %d", v, typeNum)
127+
}
128+
for i := uint(0); i < size; i++ {
129+
var key []byte
130+
key, offset, err = d.decodeKey(offset)
131+
if err != nil {
132+
return err
133+
}
134+
if string(key) == v {
135+
continue PATH
136+
}
137+
offset, err = d.nextValueOffset(offset, 1)
138+
if err != nil {
139+
return err
140+
}
141+
}
142+
// Not found. Maybe return a boolean?
143+
return nil
144+
case int:
145+
// We are expecting an array
146+
if typeNum != _Slice {
147+
// XXX - use type names in errors.
148+
return fmt.Errorf("expected a slice for %d but found %d", v, typeNum)
149+
}
150+
if size < uint(v) {
151+
// Slice is smaller than index, not found
152+
return nil
153+
}
154+
// TODO: support negative indexes? Seems useful for subdivisions in
155+
// particular.
156+
offset, err = d.nextValueOffset(offset, uint(v))
157+
if err != nil {
158+
return err
159+
}
160+
default:
161+
return fmt.Errorf("unexpected type for %d value in path, %v: %T", i, v, v)
162+
}
163+
}
164+
_, err := d.decode(offset, result, len(path))
165+
return err
166+
}
167+
92168
func (d *decoder) decodeCtrlData(offset uint) (dataType, uint, uint, error) {
93169
newOffset := offset + 1
94170
if offset >= uint(len(d.buffer)) {

decoder_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ func validateDecoding(t *testing.T, tests map[string]any) {
207207
for inputStr, expected := range tests {
208208
inputBytes, err := hex.DecodeString(inputStr)
209209
require.NoError(t, err)
210-
d := decoder{inputBytes}
210+
d := decoder{buffer: inputBytes}
211211

212212
var result any
213213
_, err = d.decode(0, reflect.ValueOf(&result), 0)
@@ -223,7 +223,7 @@ func validateDecoding(t *testing.T, tests map[string]any) {
223223
func TestPointers(t *testing.T) {
224224
bytes, err := os.ReadFile(testFile("maps-with-pointers.raw"))
225225
require.NoError(t, err)
226-
d := decoder{bytes}
226+
d := decoder{buffer: bytes}
227227

228228
expected := map[uint]map[string]string{
229229
0: {"long_key": "long_value1"},

deserializer_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package maxminddb
22

33
import (
44
"math/big"
5-
"net"
5+
"net/netip"
66
"testing"
77

88
"github.com/stretchr/testify/require"
@@ -13,7 +13,7 @@ func TestDecodingToDeserializer(t *testing.T) {
1313
require.NoError(t, err, "unexpected error while opening database: %v", err)
1414

1515
dser := testDeserializer{}
16-
err = reader.Lookup(net.ParseIP("::1.1.1.0"), &dser)
16+
err = reader.Lookup(netip.MustParseAddr("::1.1.1.0")).Decode(&dser)
1717
require.NoError(t, err, "unexpected error while doing lookup: %v", err)
1818

1919
checkDecodingToInterface(t, dser.rv)

example_test.go

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package maxminddb_test
33
import (
44
"fmt"
55
"log"
6-
"net"
6+
"net/netip"
77

8-
"github.com/oschwald/maxminddb-golang"
8+
"github.com/oschwald/maxminddb-golang/v2"
99
)
1010

1111
// This example shows how to decode to a struct.
@@ -16,15 +16,15 @@ func ExampleReader_Lookup_struct() {
1616
}
1717
defer db.Close()
1818

19-
ip := net.ParseIP("81.2.69.142")
19+
addr := netip.MustParseAddr("81.2.69.142")
2020

2121
var record struct {
2222
Country struct {
2323
ISOCode string `maxminddb:"iso_code"`
2424
} `maxminddb:"country"`
2525
} // Or any appropriate struct
2626

27-
err = db.Lookup(ip, &record)
27+
err = db.Lookup(addr).Decode(&record)
2828
if err != nil {
2929
log.Panic(err)
3030
}
@@ -41,10 +41,10 @@ func ExampleReader_Lookup_interface() {
4141
}
4242
defer db.Close()
4343

44-
ip := net.ParseIP("81.2.69.142")
44+
addr := netip.MustParseAddr("81.2.69.142")
4545

4646
var record any
47-
err = db.Lookup(ip, &record)
47+
err = db.Lookup(addr).Decode(&record)
4848
if err != nil {
4949
log.Panic(err)
5050
}
@@ -63,20 +63,16 @@ func ExampleReader_Networks() {
6363
}
6464
defer db.Close()
6565

66-
networks := db.Networks(maxminddb.SkipAliasedNetworks)
67-
for networks.Next() {
66+
for result := range db.Networks() {
6867
record := struct {
6968
Domain string `maxminddb:"connection_type"`
7069
}{}
7170

72-
subnet, err := networks.Network(&record)
71+
err := result.Decode(&record)
7372
if err != nil {
7473
log.Panic(err)
7574
}
76-
fmt.Printf("%s: %s\n", subnet.String(), record.Domain)
77-
}
78-
if networks.Err() != nil {
79-
log.Panic(networks.Err())
75+
fmt.Printf("%s: %s\n", result.Prefix(), record.Domain)
8076
}
8177
// Output:
8278
// 1.0.0.0/24: Cable/DSL
@@ -114,25 +110,20 @@ func ExampleReader_NetworksWithin() {
114110
}
115111
defer db.Close()
116112

117-
_, network, err := net.ParseCIDR("1.0.0.0/8")
113+
prefix, err := netip.ParsePrefix("1.0.0.0/8")
118114
if err != nil {
119115
log.Panic(err)
120116
}
121117

122-
networks := db.NetworksWithin(network, maxminddb.SkipAliasedNetworks)
123-
for networks.Next() {
118+
for result := range db.NetworksWithin(prefix) {
124119
record := struct {
125120
Domain string `maxminddb:"connection_type"`
126121
}{}
127-
128-
subnet, err := networks.Network(&record)
122+
err := result.Decode(&record)
129123
if err != nil {
130124
log.Panic(err)
131125
}
132-
fmt.Printf("%s: %s\n", subnet.String(), record.Domain)
133-
}
134-
if networks.Err() != nil {
135-
log.Panic(networks.Err())
126+
fmt.Printf("%s: %s\n", result.Prefix(), record.Domain)
136127
}
137128

138129
// Output:

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
module github.com/oschwald/maxminddb-golang
1+
module github.com/oschwald/maxminddb-golang/v2
22

3-
go 1.21
3+
go 1.23
44

55
require (
66
github.com/stretchr/testify v1.9.0

0 commit comments

Comments
 (0)