From 51f312aa5777f380abd2d100212317f249cd7f2c Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Sun, 18 Aug 2024 16:09:18 -0700 Subject: [PATCH] Remove (*Reader).Decode And replace it with (*Reader).LookupOffset --- reader.go | 24 +++++------------------- reader_test.go | 17 +++++++++++------ 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/reader.go b/reader.go index e9f76c3..c52dedc 100644 --- a/reader.go +++ b/reader.go @@ -150,28 +150,14 @@ func (r *Reader) Lookup(ip netip.Addr) Result { } } -// Decode the record at |offset| into |result|. The result value pointed to -// must be a data value that corresponds to a record in the database. This may -// include a struct representation of the data, a map capable of holding the -// data or an empty any value. -// -// If result is a pointer to a struct, the struct need not include a field -// for every value that may be in the database. If a field is not present in -// the structure, the decoder will not decode that field, reducing the time -// required to decode the record. -// -// As a special case, a struct field of type uintptr will be used to capture -// the offset of the value. Decode may later be used to extract the stored -// value from the offset. MaxMind DBs are highly normalized: for example in -// the City database, all records of the same country will reference a -// single representative record for that country. This uintptr behavior allows -// clients to leverage this normalization in their own sub-record caching. -func (r *Reader) Decode(offset uintptr, result any) error { +// LookupOffset returns the Result for the specified offset. Note that +// netip.Prefix returned by Networks will be invalid when using LookupOffset. +func (r *Reader) LookupOffset(offset uintptr) Result { if r.buffer == nil { - return errors.New("cannot call Decode on a closed database") + return Result{err: errors.New("cannot call Decode on a closed database")} } - return Result{decoder: r.decoder, offset: uint(offset)}.Decode(result) + return Result{decoder: r.decoder, offset: uint(offset)} } var zeroIP = netip.MustParseAddr("::") diff --git a/reader_test.go b/reader_test.go index 3976b84..968bbdd 100644 --- a/reader_test.go +++ b/reader_test.go @@ -311,7 +311,8 @@ func TestDecoder(t *testing.T) { require.NoError(t, result.Err()) require.True(t, result.Found()) - require.NoError(t, reader.Decode(result.RecordOffset(), &testV)) + res := reader.LookupOffset(result.RecordOffset()) + require.NoError(t, res.Decode(&testV)) verify(testV) } @@ -563,21 +564,25 @@ func TestNestedOffsetDecode(t *testing.T) { TimeZoneOffset uintptr `maxminddb:"time_zone"` } `maxminddb:"location"` } - require.NoError(t, db.Decode(result.RecordOffset(), &root)) + res := db.LookupOffset(result.RecordOffset()) + require.NoError(t, res.Decode(&root)) assert.InEpsilon(t, 51.5142, root.Location.Latitude, 1e-10) var longitude float64 - require.NoError(t, db.Decode(root.Location.LongitudeOffset, &longitude)) + res = db.LookupOffset(root.Location.LongitudeOffset) + require.NoError(t, res.Decode(&longitude)) assert.InEpsilon(t, -0.0931, longitude, 1e-10) var timeZone string - require.NoError(t, db.Decode(root.Location.TimeZoneOffset, &timeZone)) + res = db.LookupOffset(root.Location.TimeZoneOffset) + require.NoError(t, res.Decode(&timeZone)) assert.Equal(t, "Europe/London", timeZone) var country struct { IsoCode string `maxminddb:"iso_code"` } - require.NoError(t, db.Decode(root.CountryOffset, &country)) + res = db.LookupOffset(root.CountryOffset) + require.NoError(t, res.Decode(&country)) assert.Equal(t, "GB", country.IsoCode) require.NoError(t, db.Close()) @@ -680,7 +685,7 @@ func TestUsingClosedDatabase(t *testing.T) { err = reader.Lookup(addr).Decode(recordInterface) assert.Equal(t, "cannot call Lookup on a closed database", err.Error()) - err = reader.Decode(0, recordInterface) + err = reader.LookupOffset(0).Decode(recordInterface) assert.Equal(t, "cannot call Decode on a closed database", err.Error()) }