@@ -220,3 +220,82 @@ func TestNestedUnmarshalerInMap(t *testing.T) {
220220 require .Equal (t , "map:value2" , result ["key2" ].Data )
221221 })
222222}
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