binary-decode.go
func (cdc *Codec) decodeReflectBinaryArray(bz []byte, info *TypeInfo, rv reflect.Value, fopts FieldOptions, bare bool) (n int, err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if printLog {
		fmt.Println("(d) decodeReflectBinaryArray")
		defer func() {
			fmt.Printf("(d) -> err: %v\n", err)
		}()
	}
	ert := info.Type.Elem()
	if ert.Kind() == reflect.Uint8 {
		panic("should not happen")
	}
	length := info.Type.Len()
	einfo, err := cdc.getTypeInfo_wlock(ert)
	if err != nil {
		return
	}

	if !bare {
		// Read byte-length prefixed byteslice.
		var buf, _n = []byte(nil), int(0)
		buf, _n, err = DecodeByteSlice(bz)
		if slide(&bz, nil, _n) && err != nil {
			return
		}
		// This is a trick for debuggability -- we slide on &n more later.
		n += UvarintSize(uint64(len(buf)))
		bz = buf
	}

	// If elem is not already a ByteLength type, read in packed form.
	// This is a Proto wart due to Proto backwards compatibility issues.
	// Amino2 will probably migrate to use the List typ3.
	typ3 := typeToTyp3(einfo.Type, fopts)
	if typ3 != Typ3_ByteLength {
		// Read elements in packed form.
		for i := 0; i < length; i++ {
			var erv, _n = rv.Index(i), int(0)
			_n, err = cdc.decodeReflectBinary(bz, einfo, erv, fopts, false)
			if slide(&bz, &n, _n) && err != nil {
				err = fmt.Errorf("error reading array contents: %v", err)
				return
			}
			// Special case when reading default value, prefer nil.
			if erv.Kind() == reflect.Ptr {
				_, isDefault := isDefaultValue(erv)
				if isDefault {
					erv.Set(reflect.Zero(erv.Type()))
					continue
				}
			}
		}
		// Ensure that we read the whole buffer.
		if len(bz) > 0 {
			err = errors.New("bytes left over after reading array contents")
			return
		}
	} else {
		// NOTE: ert is for the element value, while einfo.Type is dereferenced.
		isErtStructPointer := ert.Kind() == reflect.Ptr && einfo.Type.Kind() == reflect.Struct

		// Read elements in unpacked form.
		for i := 0; i < length; i++ {
			// Read field key (number and type).
			var fnum, typ, _n = uint32(0), Typ3(0x00), int(0)
			fnum, typ, _n, err = decodeFieldNumberAndTyp3(bz)
			// Validate field number and typ3.
			if fnum != fopts.BinFieldNum {
				err = errors.New(fmt.Sprintf("expected repeated field number %v, got %v", fopts.BinFieldNum, fnum))
				return
			}
			if typ != Typ3_ByteLength {
				err = errors.New(fmt.Sprintf("expected repeated field type %v, got %v", Typ3_ByteLength, typ))
				return
			}
			if slide(&bz, &n, _n) && err != nil {
				return
			}
			// Decode the next ByteLength bytes into erv.
			var erv = rv.Index(i)
			// Special case if:
			//  * next ByteLength bytes are 0x00, and
			//  * - erv is not a struct pointer, or
			//    - field option doesn't have EmptyElements set
			// (the condition below uses demorgan's law)
			if (len(bz) > 0 && bz[0] == 0x00) &&
				!(isErtStructPointer && fopts.EmptyElements) {

				slide(&bz, &n, 1)
				erv.Set(defaultValue(erv.Type()))
				continue
			}
			// Normal case, read next non-nil element from bz.
			// In case of any inner lists in unpacked form.
			efopts := fopts
			efopts.BinFieldNum = 1
			_n, err = cdc.decodeReflectBinary(bz, einfo, erv, efopts, false)
			if slide(&bz, &n, _n) && err != nil {
				err = fmt.Errorf("error reading array contents: %v", err)
				return
			}
		}
		// Ensure that there are no more elements left,
		// and no field number regression either.
		// This is to provide better error messages.
		if len(bz) > 0 {
			var fnum = uint32(0)
			fnum, _, _, err = decodeFieldNumberAndTyp3(bz)
			if err != nil {
				return
			}
			if fnum <= fopts.BinFieldNum {
				err = fmt.Errorf("unexpected field number %v after repeated field number %v", fnum, fopts.BinFieldNum)
				return
			}
		}
	}
	return
}
func (cdc *Codec) decodeReflectBinaryArray(bz []byte, info *TypeInfo, rv reflect.Value, fopts FieldOptions, bare bool) (n int, err error) {
	if !rv.CanAddr() {
		panic("rv not addressable")
	}
	if printLog {
		fmt.Println("(d) decodeReflectBinaryArray")
		defer func() {
			fmt.Printf("(d) -> err: %v\n", err)
		}()
	}
	ert := info.Type.Elem()
	if ert.Kind() == reflect.Uint8 {
		panic("should not happen")
	}
	length := info.Type.Len()
	einfo, err := cdc.getTypeInfo_wlock(ert)
	if err != nil {
		return
	}

	if !bare {
		// Read byte-length prefixed byteslice.
		var buf, _n = []byte(nil), int(0)
		buf, _n, err = DecodeByteSlice(bz)
		if slide(&bz, nil, _n) && err != nil {
			return
		}
		// This is a trick for debuggability -- we slide on &n more later.
		n += UvarintSize(uint64(len(buf)))
		bz = buf
	}

	// If elem is not already a ByteLength type, read in packed form.
	// This is a Proto wart due to Proto backwards compatibility issues.
	// Amino2 will probably migrate to use the List typ3.
	typ3 := typeToTyp3(einfo.Type, fopts)
	if typ3 != Typ3_ByteLength {
		// Read elements in packed form.
		for i := 0; i < length; i++ {
			var erv, _n = rv.Index(i), int(0)
			_n, err = cdc.decodeReflectBinary(bz, einfo, erv, fopts, false)
			if slide(&bz, &n, _n) && err != nil {
				err = fmt.Errorf("error reading array contents: %v", err)
				return
			}
			// Special case when reading default value, prefer nil.
			if erv.Kind() == reflect.Ptr {
				_, isDefault := isDefaultValue(erv)
				if isDefault {
					erv.Set(reflect.Zero(erv.Type()))
					continue
				}
			}
		}
		// Ensure that we read the whole buffer.
		if len(bz) > 0 {
			err = errors.New("bytes left over after reading array contents")
			return
		}
	} else {
		// NOTE: ert is for the element value, while einfo.Type is dereferenced.
		isErtStructPointer := ert.Kind() == reflect.Ptr && einfo.Type.Kind() == reflect.Struct

		// Read elements in unpacked form.
		for i := 0; i < length; i++ {
			// Read field key (number and type).
			var fnum, typ, _n = uint32(0), Typ3(0x00), int(0)
			fnum, typ, _n, err = decodeFieldNumberAndTyp3(bz)
			// Validate field number and typ3.
			if fnum != fopts.BinFieldNum {
				err = errors.New(fmt.Sprintf("expected repeated field number %v, got %v", fopts.BinFieldNum, fnum))
				return
			}
			if typ != Typ3_ByteLength {
				err = errors.New(fmt.Sprintf("expected repeated field type %v, got %v", Typ3_ByteLength, typ))
				return
			}
			if slide(&bz, &n, _n) && err != nil {
				return
			}
			// Decode the next ByteLength bytes into erv.
			var erv = rv.Index(i)
			// Special case if:
			//  * next ByteLength bytes are 0x00, and
			//  * - erv is not a struct pointer, or
			//    - field option doesn't have EmptyElements set
			// (the condition below uses demorgan's law)
			if (len(bz) > 0 && bz[0] == 0x00) &&
				!(isErtStructPointer && fopts.EmptyElements) {

				slide(&bz, &n, 1)
				erv.Set(defaultValue(erv.Type()))
				continue
			}
			// Normal case, read next non-nil element from bz.
			// In case of any inner lists in unpacked form.
			efopts := fopts
			efopts.BinFieldNum = 1
			_n, err = cdc.decodeReflectBinary(bz, einfo, erv, efopts, false)
			if slide(&bz, &n, _n) && err != nil {
				err = fmt.Errorf("error reading array contents: %v", err)
				return
			}
		}
		// Ensure that there are no more elements left,
		// and no field number regression either.
		// This is to provide better error messages.
		if len(bz) > 0 {
			var fnum = uint32(0)
			fnum, _, _, err = decodeFieldNumberAndTyp3(bz)
			if err != nil {
				return
			}
			if fnum <= fopts.BinFieldNum {
				err = fmt.Errorf("unexpected field number %v after repeated field number %v", fnum, fopts.BinFieldNum)
				return
			}
		}
	}
	return
}
// CONTRACT: rv.CanAddr() is true.
// NOTE: Keep the code structure similar to decodeReflectBinarySlice.