@@ -220,3 +220,82 @@ func TestNestedUnmarshalerInMap(t *testing.T) {
220
220
require .Equal (t , "map:value2" , result ["key2" ].Data )
221
221
})
222
222
}
223
+
224
+ // testMapIterator uses ReadMap() iterator to simulate mmdbtype.Map behavior.
225
+ type testMapIterator struct {
226
+ Values map [string ]string
227
+ custom bool
228
+ }
229
+
230
+ func (m * testMapIterator ) UnmarshalMaxMindDB (d * Decoder ) error {
231
+ m .custom = true
232
+ iter , size , err := d .ReadMap ()
233
+ if err != nil {
234
+ return err
235
+ }
236
+
237
+ m .Values = make (map [string ]string , size )
238
+ for key , iterErr := range iter {
239
+ if iterErr != nil {
240
+ return iterErr
241
+ }
242
+
243
+ // Read the value as a string
244
+ value , err := d .ReadString ()
245
+ if err != nil {
246
+ return err
247
+ }
248
+
249
+ m .Values [string (key )] = value
250
+ }
251
+ return nil
252
+ }
253
+
254
+ // TestCustomUnmarshalerWithIterator tests that custom unmarshalers using iterators
255
+ // work correctly in struct fields. This reproduces the original "no next offset available"
256
+ // issue that occurred when mmdbtype.Map was used in structs.
257
+ func TestCustomUnmarshalerWithIterator (t * testing.T ) {
258
+ type Record struct {
259
+ Name string
260
+ Location testMapIterator // This field uses ReadMap() iterator
261
+ Country string
262
+ }
263
+
264
+ data := []byte {
265
+ // Map with 3 items
266
+ 0xe3 ,
267
+ // Key "Name"
268
+ 0x44 , 'N' , 'a' , 'm' , 'e' ,
269
+ // Value "Test" (string)
270
+ 0x44 , 'T' , 'e' , 's' , 't' ,
271
+ // Key "Location"
272
+ 0x48 , 'L' , 'o' , 'c' , 'a' , 't' , 'i' , 'o' , 'n' ,
273
+ // Value: Map with 2 items (latitude and longitude)
274
+ 0xe2 ,
275
+ // Key "lat"
276
+ 0x43 , 'l' , 'a' , 't' ,
277
+ // Value "40.7"
278
+ 0x44 , '4' , '0' , '.' , '7' ,
279
+ // Key "lng"
280
+ 0x43 , 'l' , 'n' , 'g' ,
281
+ // Value "-74.0"
282
+ 0x45 , '-' , '7' , '4' , '.' , '0' ,
283
+ // Key "Country"
284
+ 0x47 , 'C' , 'o' , 'u' , 'n' , 't' , 'r' , 'y' ,
285
+ // Value "US"
286
+ 0x42 , 'U' , 'S' ,
287
+ }
288
+
289
+ d := New (data )
290
+ var result Record
291
+
292
+ err := d .Decode (0 , & result )
293
+ require .NoError (t , err )
294
+
295
+ require .Equal (t , "Test" , result .Name )
296
+ require .True (t , result .Location .custom , "Custom unmarshaler should be called" )
297
+ require .Len (t , result .Location .Values , 2 )
298
+ require .Equal (t , "40.7" , result .Location .Values ["lat" ])
299
+ require .Equal (t , "-74.0" , result .Location .Values ["lng" ])
300
+ require .Equal (t , "US" , result .Country )
301
+ }
0 commit comments