git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/mmdb/decoder.go (about)

     1  package mmdb
     2  
     3  import (
     4  	"encoding/binary"
     5  	"math"
     6  	"math/big"
     7  	"reflect"
     8  	"sync"
     9  )
    10  
    11  type decoder struct {
    12  	buffer []byte
    13  }
    14  
    15  type dataType int
    16  
    17  const (
    18  	_Extended dataType = iota
    19  	_Pointer
    20  	_String
    21  	_Float64
    22  	_Bytes
    23  	_Uint16
    24  	_Uint32
    25  	_Map
    26  	_Int32
    27  	_Uint64
    28  	_Uint128
    29  	_Slice
    30  	// We don't use the next two. They are placeholders. See the spec
    31  	// for more details.
    32  	_Container //nolint: deadcode, varcheck // above
    33  	_Marker    //nolint: deadcode, varcheck // above
    34  	_Bool
    35  	_Float32
    36  )
    37  
    38  const (
    39  	// This is the value used in libmaxminddb.
    40  	maximumDataStructureDepth = 512
    41  )
    42  
    43  func (d *decoder) decode(offset uint, result reflect.Value, depth int) (uint, error) {
    44  	if depth > maximumDataStructureDepth {
    45  		return 0, newInvalidDatabaseError(
    46  			"exceeded maximum data structure depth; database is likely corrupt",
    47  		)
    48  	}
    49  	typeNum, size, newOffset, err := d.decodeCtrlData(offset)
    50  	if err != nil {
    51  		return 0, err
    52  	}
    53  
    54  	if typeNum != _Pointer && result.Kind() == reflect.Uintptr {
    55  		result.Set(reflect.ValueOf(uintptr(offset)))
    56  		return d.nextValueOffset(offset, 1)
    57  	}
    58  	return d.decodeFromType(typeNum, size, newOffset, result, depth+1)
    59  }
    60  
    61  func (d *decoder) decodeToDeserializer(
    62  	offset uint,
    63  	dser deserializer,
    64  	depth int,
    65  	getNext bool,
    66  ) (uint, error) {
    67  	if depth > maximumDataStructureDepth {
    68  		return 0, newInvalidDatabaseError(
    69  			"exceeded maximum data structure depth; database is likely corrupt",
    70  		)
    71  	}
    72  	skip, err := dser.ShouldSkip(uintptr(offset))
    73  	if err != nil {
    74  		return 0, err
    75  	}
    76  	if skip {
    77  		if getNext {
    78  			return d.nextValueOffset(offset, 1)
    79  		}
    80  		return 0, nil
    81  	}
    82  
    83  	typeNum, size, newOffset, err := d.decodeCtrlData(offset)
    84  	if err != nil {
    85  		return 0, err
    86  	}
    87  
    88  	return d.decodeFromTypeToDeserializer(typeNum, size, newOffset, dser, depth+1)
    89  }
    90  
    91  func (d *decoder) decodeCtrlData(offset uint) (dataType, uint, uint, error) {
    92  	newOffset := offset + 1
    93  	if offset >= uint(len(d.buffer)) {
    94  		return 0, 0, 0, newOffsetError()
    95  	}
    96  	ctrlByte := d.buffer[offset]
    97  
    98  	typeNum := dataType(ctrlByte >> 5)
    99  	if typeNum == _Extended {
   100  		if newOffset >= uint(len(d.buffer)) {
   101  			return 0, 0, 0, newOffsetError()
   102  		}
   103  		typeNum = dataType(d.buffer[newOffset] + 7)
   104  		newOffset++
   105  	}
   106  
   107  	var size uint
   108  	size, newOffset, err := d.sizeFromCtrlByte(ctrlByte, newOffset, typeNum)
   109  	return typeNum, size, newOffset, err
   110  }
   111  
   112  func (d *decoder) sizeFromCtrlByte(
   113  	ctrlByte byte,
   114  	offset uint,
   115  	typeNum dataType,
   116  ) (uint, uint, error) {
   117  	size := uint(ctrlByte & 0x1f)
   118  	if typeNum == _Extended {
   119  		return size, offset, nil
   120  	}
   121  
   122  	var bytesToRead uint
   123  	if size < 29 {
   124  		return size, offset, nil
   125  	}
   126  
   127  	bytesToRead = size - 28
   128  	newOffset := offset + bytesToRead
   129  	if newOffset > uint(len(d.buffer)) {
   130  		return 0, 0, newOffsetError()
   131  	}
   132  	if size == 29 {
   133  		return 29 + uint(d.buffer[offset]), offset + 1, nil
   134  	}
   135  
   136  	sizeBytes := d.buffer[offset:newOffset]
   137  
   138  	switch {
   139  	case size == 30:
   140  		size = 285 + uintFromBytes(0, sizeBytes)
   141  	case size > 30:
   142  		size = uintFromBytes(0, sizeBytes) + 65821
   143  	}
   144  	return size, newOffset, nil
   145  }
   146  
   147  func (d *decoder) decodeFromType(
   148  	dtype dataType,
   149  	size uint,
   150  	offset uint,
   151  	result reflect.Value,
   152  	depth int,
   153  ) (uint, error) {
   154  	result = indirect(result)
   155  
   156  	// For these types, size has a special meaning
   157  	switch dtype {
   158  	case _Bool:
   159  		return unmarshalBool(size, offset, result)
   160  	case _Map:
   161  		return d.unmarshalMap(size, offset, result, depth)
   162  	case _Pointer:
   163  		return d.unmarshalPointer(size, offset, result, depth)
   164  	case _Slice:
   165  		return d.unmarshalSlice(size, offset, result, depth)
   166  	}
   167  
   168  	// For the remaining types, size is the byte size
   169  	if offset+size > uint(len(d.buffer)) {
   170  		return 0, newOffsetError()
   171  	}
   172  	switch dtype {
   173  	case _Bytes:
   174  		return d.unmarshalBytes(size, offset, result)
   175  	case _Float32:
   176  		return d.unmarshalFloat32(size, offset, result)
   177  	case _Float64:
   178  		return d.unmarshalFloat64(size, offset, result)
   179  	case _Int32:
   180  		return d.unmarshalInt32(size, offset, result)
   181  	case _String:
   182  		return d.unmarshalString(size, offset, result)
   183  	case _Uint16:
   184  		return d.unmarshalUint(size, offset, result, 16)
   185  	case _Uint32:
   186  		return d.unmarshalUint(size, offset, result, 32)
   187  	case _Uint64:
   188  		return d.unmarshalUint(size, offset, result, 64)
   189  	case _Uint128:
   190  		return d.unmarshalUint128(size, offset, result)
   191  	default:
   192  		return 0, newInvalidDatabaseError("unknown type: %d", dtype)
   193  	}
   194  }
   195  
   196  func (d *decoder) decodeFromTypeToDeserializer(
   197  	dtype dataType,
   198  	size uint,
   199  	offset uint,
   200  	dser deserializer,
   201  	depth int,
   202  ) (uint, error) {
   203  	// For these types, size has a special meaning
   204  	switch dtype {
   205  	case _Bool:
   206  		v, offset := decodeBool(size, offset)
   207  		return offset, dser.Bool(v)
   208  	case _Map:
   209  		return d.decodeMapToDeserializer(size, offset, dser, depth)
   210  	case _Pointer:
   211  		pointer, newOffset, err := d.decodePointer(size, offset)
   212  		if err != nil {
   213  			return 0, err
   214  		}
   215  		_, err = d.decodeToDeserializer(pointer, dser, depth, false)
   216  		return newOffset, err
   217  	case _Slice:
   218  		return d.decodeSliceToDeserializer(size, offset, dser, depth)
   219  	}
   220  
   221  	// For the remaining types, size is the byte size
   222  	if offset+size > uint(len(d.buffer)) {
   223  		return 0, newOffsetError()
   224  	}
   225  	switch dtype {
   226  	case _Bytes:
   227  		v, offset := d.decodeBytes(size, offset)
   228  		return offset, dser.Bytes(v)
   229  	case _Float32:
   230  		v, offset := d.decodeFloat32(size, offset)
   231  		return offset, dser.Float32(v)
   232  	case _Float64:
   233  		v, offset := d.decodeFloat64(size, offset)
   234  		return offset, dser.Float64(v)
   235  	case _Int32:
   236  		v, offset := d.decodeInt(size, offset)
   237  		return offset, dser.Int32(int32(v))
   238  	case _String:
   239  		v, offset := d.decodeString(size, offset)
   240  		return offset, dser.String(v)
   241  	case _Uint16:
   242  		v, offset := d.decodeUint(size, offset)
   243  		return offset, dser.Uint16(uint16(v))
   244  	case _Uint32:
   245  		v, offset := d.decodeUint(size, offset)
   246  		return offset, dser.Uint32(uint32(v))
   247  	case _Uint64:
   248  		v, offset := d.decodeUint(size, offset)
   249  		return offset, dser.Uint64(v)
   250  	case _Uint128:
   251  		v, offset := d.decodeUint128(size, offset)
   252  		return offset, dser.Uint128(v)
   253  	default:
   254  		return 0, newInvalidDatabaseError("unknown type: %d", dtype)
   255  	}
   256  }
   257  
   258  func unmarshalBool(size, offset uint, result reflect.Value) (uint, error) {
   259  	if size > 1 {
   260  		return 0, newInvalidDatabaseError(
   261  			"the MaxMind DB file's data section contains bad data (bool size of %v)",
   262  			size,
   263  		)
   264  	}
   265  	value, newOffset := decodeBool(size, offset)
   266  
   267  	switch result.Kind() {
   268  	case reflect.Bool:
   269  		result.SetBool(value)
   270  		return newOffset, nil
   271  	case reflect.Interface:
   272  		if result.NumMethod() == 0 {
   273  			result.Set(reflect.ValueOf(value))
   274  			return newOffset, nil
   275  		}
   276  	}
   277  	return newOffset, newUnmarshalTypeError(value, result.Type())
   278  }
   279  
   280  // indirect follows pointers and create values as necessary. This is
   281  // heavily based on encoding/json as my original version had a subtle
   282  // bug. This method should be considered to be licensed under
   283  // https://golang.org/LICENSE
   284  func indirect(result reflect.Value) reflect.Value {
   285  	for {
   286  		// Load value from interface, but only if the result will be
   287  		// usefully addressable.
   288  		if result.Kind() == reflect.Interface && !result.IsNil() {
   289  			e := result.Elem()
   290  			if e.Kind() == reflect.Ptr && !e.IsNil() {
   291  				result = e
   292  				continue
   293  			}
   294  		}
   295  
   296  		if result.Kind() != reflect.Ptr {
   297  			break
   298  		}
   299  
   300  		if result.IsNil() {
   301  			result.Set(reflect.New(result.Type().Elem()))
   302  		}
   303  
   304  		result = result.Elem()
   305  	}
   306  	return result
   307  }
   308  
   309  var sliceType = reflect.TypeOf([]byte{})
   310  
   311  func (d *decoder) unmarshalBytes(size, offset uint, result reflect.Value) (uint, error) {
   312  	value, newOffset := d.decodeBytes(size, offset)
   313  
   314  	switch result.Kind() {
   315  	case reflect.Slice:
   316  		if result.Type() == sliceType {
   317  			result.SetBytes(value)
   318  			return newOffset, nil
   319  		}
   320  	case reflect.Interface:
   321  		if result.NumMethod() == 0 {
   322  			result.Set(reflect.ValueOf(value))
   323  			return newOffset, nil
   324  		}
   325  	}
   326  	return newOffset, newUnmarshalTypeError(value, result.Type())
   327  }
   328  
   329  func (d *decoder) unmarshalFloat32(size, offset uint, result reflect.Value) (uint, error) {
   330  	if size != 4 {
   331  		return 0, newInvalidDatabaseError(
   332  			"the MaxMind DB file's data section contains bad data (float32 size of %v)",
   333  			size,
   334  		)
   335  	}
   336  	value, newOffset := d.decodeFloat32(size, offset)
   337  
   338  	switch result.Kind() {
   339  	case reflect.Float32, reflect.Float64:
   340  		result.SetFloat(float64(value))
   341  		return newOffset, nil
   342  	case reflect.Interface:
   343  		if result.NumMethod() == 0 {
   344  			result.Set(reflect.ValueOf(value))
   345  			return newOffset, nil
   346  		}
   347  	}
   348  	return newOffset, newUnmarshalTypeError(value, result.Type())
   349  }
   350  
   351  func (d *decoder) unmarshalFloat64(size, offset uint, result reflect.Value) (uint, error) {
   352  	if size != 8 {
   353  		return 0, newInvalidDatabaseError(
   354  			"the MaxMind DB file's data section contains bad data (float 64 size of %v)",
   355  			size,
   356  		)
   357  	}
   358  	value, newOffset := d.decodeFloat64(size, offset)
   359  
   360  	switch result.Kind() {
   361  	case reflect.Float32, reflect.Float64:
   362  		if result.OverflowFloat(value) {
   363  			return 0, newUnmarshalTypeError(value, result.Type())
   364  		}
   365  		result.SetFloat(value)
   366  		return newOffset, nil
   367  	case reflect.Interface:
   368  		if result.NumMethod() == 0 {
   369  			result.Set(reflect.ValueOf(value))
   370  			return newOffset, nil
   371  		}
   372  	}
   373  	return newOffset, newUnmarshalTypeError(value, result.Type())
   374  }
   375  
   376  func (d *decoder) unmarshalInt32(size, offset uint, result reflect.Value) (uint, error) {
   377  	if size > 4 {
   378  		return 0, newInvalidDatabaseError(
   379  			"the MaxMind DB file's data section contains bad data (int32 size of %v)",
   380  			size,
   381  		)
   382  	}
   383  	value, newOffset := d.decodeInt(size, offset)
   384  
   385  	switch result.Kind() {
   386  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   387  		n := int64(value)
   388  		if !result.OverflowInt(n) {
   389  			result.SetInt(n)
   390  			return newOffset, nil
   391  		}
   392  	case reflect.Uint,
   393  		reflect.Uint8,
   394  		reflect.Uint16,
   395  		reflect.Uint32,
   396  		reflect.Uint64,
   397  		reflect.Uintptr:
   398  		n := uint64(value)
   399  		if !result.OverflowUint(n) {
   400  			result.SetUint(n)
   401  			return newOffset, nil
   402  		}
   403  	case reflect.Interface:
   404  		if result.NumMethod() == 0 {
   405  			result.Set(reflect.ValueOf(value))
   406  			return newOffset, nil
   407  		}
   408  	}
   409  	return newOffset, newUnmarshalTypeError(value, result.Type())
   410  }
   411  
   412  func (d *decoder) unmarshalMap(
   413  	size uint,
   414  	offset uint,
   415  	result reflect.Value,
   416  	depth int,
   417  ) (uint, error) {
   418  	result = indirect(result)
   419  	switch result.Kind() {
   420  	default:
   421  		return 0, newUnmarshalTypeError("map", result.Type())
   422  	case reflect.Struct:
   423  		return d.decodeStruct(size, offset, result, depth)
   424  	case reflect.Map:
   425  		return d.decodeMap(size, offset, result, depth)
   426  	case reflect.Interface:
   427  		if result.NumMethod() == 0 {
   428  			rv := reflect.ValueOf(make(map[string]any, size))
   429  			newOffset, err := d.decodeMap(size, offset, rv, depth)
   430  			result.Set(rv)
   431  			return newOffset, err
   432  		}
   433  		return 0, newUnmarshalTypeError("map", result.Type())
   434  	}
   435  }
   436  
   437  func (d *decoder) unmarshalPointer(
   438  	size, offset uint,
   439  	result reflect.Value,
   440  	depth int,
   441  ) (uint, error) {
   442  	pointer, newOffset, err := d.decodePointer(size, offset)
   443  	if err != nil {
   444  		return 0, err
   445  	}
   446  	_, err = d.decode(pointer, result, depth)
   447  	return newOffset, err
   448  }
   449  
   450  func (d *decoder) unmarshalSlice(
   451  	size uint,
   452  	offset uint,
   453  	result reflect.Value,
   454  	depth int,
   455  ) (uint, error) {
   456  	switch result.Kind() {
   457  	case reflect.Slice:
   458  		return d.decodeSlice(size, offset, result, depth)
   459  	case reflect.Interface:
   460  		if result.NumMethod() == 0 {
   461  			a := []any{}
   462  			rv := reflect.ValueOf(&a).Elem()
   463  			newOffset, err := d.decodeSlice(size, offset, rv, depth)
   464  			result.Set(rv)
   465  			return newOffset, err
   466  		}
   467  	}
   468  	return 0, newUnmarshalTypeError("array", result.Type())
   469  }
   470  
   471  func (d *decoder) unmarshalString(size, offset uint, result reflect.Value) (uint, error) {
   472  	value, newOffset := d.decodeString(size, offset)
   473  
   474  	switch result.Kind() {
   475  	case reflect.String:
   476  		result.SetString(value)
   477  		return newOffset, nil
   478  	case reflect.Interface:
   479  		if result.NumMethod() == 0 {
   480  			result.Set(reflect.ValueOf(value))
   481  			return newOffset, nil
   482  		}
   483  	}
   484  	return newOffset, newUnmarshalTypeError(value, result.Type())
   485  }
   486  
   487  func (d *decoder) unmarshalUint(
   488  	size, offset uint,
   489  	result reflect.Value,
   490  	uintType uint,
   491  ) (uint, error) {
   492  	if size > uintType/8 {
   493  		return 0, newInvalidDatabaseError(
   494  			"the MaxMind DB file's data section contains bad data (uint%v size of %v)",
   495  			uintType,
   496  			size,
   497  		)
   498  	}
   499  
   500  	value, newOffset := d.decodeUint(size, offset)
   501  
   502  	switch result.Kind() {
   503  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   504  		n := int64(value)
   505  		if !result.OverflowInt(n) {
   506  			result.SetInt(n)
   507  			return newOffset, nil
   508  		}
   509  	case reflect.Uint,
   510  		reflect.Uint8,
   511  		reflect.Uint16,
   512  		reflect.Uint32,
   513  		reflect.Uint64,
   514  		reflect.Uintptr:
   515  		if !result.OverflowUint(value) {
   516  			result.SetUint(value)
   517  			return newOffset, nil
   518  		}
   519  	case reflect.Interface:
   520  		if result.NumMethod() == 0 {
   521  			result.Set(reflect.ValueOf(value))
   522  			return newOffset, nil
   523  		}
   524  	}
   525  	return newOffset, newUnmarshalTypeError(value, result.Type())
   526  }
   527  
   528  var bigIntType = reflect.TypeOf(big.Int{})
   529  
   530  func (d *decoder) unmarshalUint128(size, offset uint, result reflect.Value) (uint, error) {
   531  	if size > 16 {
   532  		return 0, newInvalidDatabaseError(
   533  			"the MaxMind DB file's data section contains bad data (uint128 size of %v)",
   534  			size,
   535  		)
   536  	}
   537  	value, newOffset := d.decodeUint128(size, offset)
   538  
   539  	switch result.Kind() {
   540  	case reflect.Struct:
   541  		if result.Type() == bigIntType {
   542  			result.Set(reflect.ValueOf(*value))
   543  			return newOffset, nil
   544  		}
   545  	case reflect.Interface:
   546  		if result.NumMethod() == 0 {
   547  			result.Set(reflect.ValueOf(value))
   548  			return newOffset, nil
   549  		}
   550  	}
   551  	return newOffset, newUnmarshalTypeError(value, result.Type())
   552  }
   553  
   554  func decodeBool(size, offset uint) (bool, uint) {
   555  	return size != 0, offset
   556  }
   557  
   558  func (d *decoder) decodeBytes(size, offset uint) ([]byte, uint) {
   559  	newOffset := offset + size
   560  	bytes := make([]byte, size)
   561  	copy(bytes, d.buffer[offset:newOffset])
   562  	return bytes, newOffset
   563  }
   564  
   565  func (d *decoder) decodeFloat64(size, offset uint) (float64, uint) {
   566  	newOffset := offset + size
   567  	bits := binary.BigEndian.Uint64(d.buffer[offset:newOffset])
   568  	return math.Float64frombits(bits), newOffset
   569  }
   570  
   571  func (d *decoder) decodeFloat32(size, offset uint) (float32, uint) {
   572  	newOffset := offset + size
   573  	bits := binary.BigEndian.Uint32(d.buffer[offset:newOffset])
   574  	return math.Float32frombits(bits), newOffset
   575  }
   576  
   577  func (d *decoder) decodeInt(size, offset uint) (int, uint) {
   578  	newOffset := offset + size
   579  	var val int32
   580  	for _, b := range d.buffer[offset:newOffset] {
   581  		val = (val << 8) | int32(b)
   582  	}
   583  	return int(val), newOffset
   584  }
   585  
   586  func (d *decoder) decodeMap(
   587  	size uint,
   588  	offset uint,
   589  	result reflect.Value,
   590  	depth int,
   591  ) (uint, error) {
   592  	if result.IsNil() {
   593  		result.Set(reflect.MakeMapWithSize(result.Type(), int(size)))
   594  	}
   595  
   596  	mapType := result.Type()
   597  	keyValue := reflect.New(mapType.Key()).Elem()
   598  	elemType := mapType.Elem()
   599  	elemKind := elemType.Kind()
   600  	var elemValue reflect.Value
   601  	for i := uint(0); i < size; i++ {
   602  		var key []byte
   603  		var err error
   604  		key, offset, err = d.decodeKey(offset)
   605  
   606  		if err != nil {
   607  			return 0, err
   608  		}
   609  
   610  		if !elemValue.IsValid() || elemKind == reflect.Interface {
   611  			elemValue = reflect.New(elemType).Elem()
   612  		}
   613  
   614  		offset, err = d.decode(offset, elemValue, depth)
   615  		if err != nil {
   616  			return 0, err
   617  		}
   618  
   619  		keyValue.SetString(string(key))
   620  		result.SetMapIndex(keyValue, elemValue)
   621  	}
   622  	return offset, nil
   623  }
   624  
   625  func (d *decoder) decodeMapToDeserializer(
   626  	size uint,
   627  	offset uint,
   628  	dser deserializer,
   629  	depth int,
   630  ) (uint, error) {
   631  	err := dser.StartMap(size)
   632  	if err != nil {
   633  		return 0, err
   634  	}
   635  	for i := uint(0); i < size; i++ {
   636  		// TODO - implement key/value skipping?
   637  		offset, err = d.decodeToDeserializer(offset, dser, depth, true)
   638  		if err != nil {
   639  			return 0, err
   640  		}
   641  
   642  		offset, err = d.decodeToDeserializer(offset, dser, depth, true)
   643  		if err != nil {
   644  			return 0, err
   645  		}
   646  	}
   647  	err = dser.End()
   648  	if err != nil {
   649  		return 0, err
   650  	}
   651  	return offset, nil
   652  }
   653  
   654  func (d *decoder) decodePointer(
   655  	size uint,
   656  	offset uint,
   657  ) (uint, uint, error) {
   658  	pointerSize := ((size >> 3) & 0x3) + 1
   659  	newOffset := offset + pointerSize
   660  	if newOffset > uint(len(d.buffer)) {
   661  		return 0, 0, newOffsetError()
   662  	}
   663  	pointerBytes := d.buffer[offset:newOffset]
   664  	var prefix uint
   665  	if pointerSize == 4 {
   666  		prefix = 0
   667  	} else {
   668  		prefix = size & 0x7
   669  	}
   670  	unpacked := uintFromBytes(prefix, pointerBytes)
   671  
   672  	var pointerValueOffset uint
   673  	switch pointerSize {
   674  	case 1:
   675  		pointerValueOffset = 0
   676  	case 2:
   677  		pointerValueOffset = 2048
   678  	case 3:
   679  		pointerValueOffset = 526336
   680  	case 4:
   681  		pointerValueOffset = 0
   682  	}
   683  
   684  	pointer := unpacked + pointerValueOffset
   685  
   686  	return pointer, newOffset, nil
   687  }
   688  
   689  func (d *decoder) decodeSlice(
   690  	size uint,
   691  	offset uint,
   692  	result reflect.Value,
   693  	depth int,
   694  ) (uint, error) {
   695  	result.Set(reflect.MakeSlice(result.Type(), int(size), int(size)))
   696  	for i := 0; i < int(size); i++ {
   697  		var err error
   698  		offset, err = d.decode(offset, result.Index(i), depth)
   699  		if err != nil {
   700  			return 0, err
   701  		}
   702  	}
   703  	return offset, nil
   704  }
   705  
   706  func (d *decoder) decodeSliceToDeserializer(
   707  	size uint,
   708  	offset uint,
   709  	dser deserializer,
   710  	depth int,
   711  ) (uint, error) {
   712  	err := dser.StartSlice(size)
   713  	if err != nil {
   714  		return 0, err
   715  	}
   716  	for i := uint(0); i < size; i++ {
   717  		offset, err = d.decodeToDeserializer(offset, dser, depth, true)
   718  		if err != nil {
   719  			return 0, err
   720  		}
   721  	}
   722  	err = dser.End()
   723  	if err != nil {
   724  		return 0, err
   725  	}
   726  	return offset, nil
   727  }
   728  
   729  func (d *decoder) decodeString(size, offset uint) (string, uint) {
   730  	newOffset := offset + size
   731  	return string(d.buffer[offset:newOffset]), newOffset
   732  }
   733  
   734  func (d *decoder) decodeStruct(
   735  	size uint,
   736  	offset uint,
   737  	result reflect.Value,
   738  	depth int,
   739  ) (uint, error) {
   740  	fields := cachedFields(result)
   741  
   742  	// This fills in embedded structs
   743  	for _, i := range fields.anonymousFields {
   744  		_, err := d.unmarshalMap(size, offset, result.Field(i), depth)
   745  		if err != nil {
   746  			return 0, err
   747  		}
   748  	}
   749  
   750  	// This handles named fields
   751  	for i := uint(0); i < size; i++ {
   752  		var (
   753  			err error
   754  			key []byte
   755  		)
   756  		key, offset, err = d.decodeKey(offset)
   757  		if err != nil {
   758  			return 0, err
   759  		}
   760  		// The string() does not create a copy due to this compiler
   761  		// optimization: https://github.com/golang/go/issues/3512
   762  		j, ok := fields.namedFields[string(key)]
   763  		if !ok {
   764  			offset, err = d.nextValueOffset(offset, 1)
   765  			if err != nil {
   766  				return 0, err
   767  			}
   768  			continue
   769  		}
   770  
   771  		offset, err = d.decode(offset, result.Field(j), depth)
   772  		if err != nil {
   773  			return 0, err
   774  		}
   775  	}
   776  	return offset, nil
   777  }
   778  
   779  type fieldsType struct {
   780  	namedFields     map[string]int
   781  	anonymousFields []int
   782  }
   783  
   784  var fieldsMap sync.Map
   785  
   786  func cachedFields(result reflect.Value) *fieldsType {
   787  	resultType := result.Type()
   788  
   789  	if fields, ok := fieldsMap.Load(resultType); ok {
   790  		return fields.(*fieldsType)
   791  	}
   792  	numFields := resultType.NumField()
   793  	namedFields := make(map[string]int, numFields)
   794  	var anonymous []int
   795  	for i := 0; i < numFields; i++ {
   796  		field := resultType.Field(i)
   797  
   798  		fieldName := field.Name
   799  		if tag := field.Tag.Get("maxminddb"); tag != "" {
   800  			if tag == "-" {
   801  				continue
   802  			}
   803  			fieldName = tag
   804  		}
   805  		if field.Anonymous {
   806  			anonymous = append(anonymous, i)
   807  			continue
   808  		}
   809  		namedFields[fieldName] = i
   810  	}
   811  	fields := &fieldsType{namedFields, anonymous}
   812  	fieldsMap.Store(resultType, fields)
   813  
   814  	return fields
   815  }
   816  
   817  func (d *decoder) decodeUint(size, offset uint) (uint64, uint) {
   818  	newOffset := offset + size
   819  	bytes := d.buffer[offset:newOffset]
   820  
   821  	var val uint64
   822  	for _, b := range bytes {
   823  		val = (val << 8) | uint64(b)
   824  	}
   825  	return val, newOffset
   826  }
   827  
   828  func (d *decoder) decodeUint128(size, offset uint) (*big.Int, uint) {
   829  	newOffset := offset + size
   830  	val := new(big.Int)
   831  	val.SetBytes(d.buffer[offset:newOffset])
   832  
   833  	return val, newOffset
   834  }
   835  
   836  func uintFromBytes(prefix uint, uintBytes []byte) uint {
   837  	val := prefix
   838  	for _, b := range uintBytes {
   839  		val = (val << 8) | uint(b)
   840  	}
   841  	return val
   842  }
   843  
   844  // decodeKey decodes a map key into []byte slice. We use a []byte so that we
   845  // can take advantage of https://github.com/golang/go/issues/3512 to avoid
   846  // copying the bytes when decoding a struct. Previously, we achieved this by
   847  // using unsafe.
   848  func (d *decoder) decodeKey(offset uint) ([]byte, uint, error) {
   849  	typeNum, size, dataOffset, err := d.decodeCtrlData(offset)
   850  	if err != nil {
   851  		return nil, 0, err
   852  	}
   853  	if typeNum == _Pointer {
   854  		pointer, ptrOffset, err := d.decodePointer(size, dataOffset)
   855  		if err != nil {
   856  			return nil, 0, err
   857  		}
   858  		key, _, err := d.decodeKey(pointer)
   859  		return key, ptrOffset, err
   860  	}
   861  	if typeNum != _String {
   862  		return nil, 0, newInvalidDatabaseError("unexpected type when decoding string: %v", typeNum)
   863  	}
   864  	newOffset := dataOffset + size
   865  	if newOffset > uint(len(d.buffer)) {
   866  		return nil, 0, newOffsetError()
   867  	}
   868  	return d.buffer[dataOffset:newOffset], newOffset, nil
   869  }
   870  
   871  // This function is used to skip ahead to the next value without decoding
   872  // the one at the offset passed in. The size bits have different meanings for
   873  // different data types.
   874  func (d *decoder) nextValueOffset(offset, numberToSkip uint) (uint, error) {
   875  	if numberToSkip == 0 {
   876  		return offset, nil
   877  	}
   878  	typeNum, size, offset, err := d.decodeCtrlData(offset)
   879  	if err != nil {
   880  		return 0, err
   881  	}
   882  	switch typeNum {
   883  	case _Pointer:
   884  		_, offset, err = d.decodePointer(size, offset)
   885  		if err != nil {
   886  			return 0, err
   887  		}
   888  	case _Map:
   889  		numberToSkip += 2 * size
   890  	case _Slice:
   891  		numberToSkip += size
   892  	case _Bool:
   893  	default:
   894  		offset += size
   895  	}
   896  	return d.nextValueOffset(offset, numberToSkip-1)
   897  }