func UnpackBlock()

in pkg/unpack/unpack.go [40:101]


func UnpackBlock(unpacked, packed []byte, radix, pre int) (int, error) {
	if len(packed) == 0 || len(unpacked) == 0 {
		return 0, nil
	}

	dpw := ycd.DigitsPerWord(radix)

	unpackedLen := UnpackedLen(int64(len(packed)-1), radix) - int64(pre)
	if int64(len(unpacked)) < unpackedLen {
		return 0, fmt.Errorf("%w: required = %v bytes, actual buffer = %v bytes",
			ErrBufferTooSmall, unpackedLen, len(unpacked))
	}

	// Unpack the first word with pre.
	// Copy dpw-pre bytes.
	s := strconv.FormatUint(binary.LittleEndian.Uint64(packed), radix)
	nz := dpw - len(s)
	if nz < 0 {
		return 0, fmt.Errorf("%w: word = %16x, unpacked = %s",
			ErrInvalidWord, packed[:WordSize], s)
	}
	nzNeeded := nz - pre
	if nzNeeded < 0 {
		nzNeeded = 0
	}
	n := copy(unpacked, zeros[:nzNeeded])
	if n < dpw-pre && n < len(unpacked) {
		if nz < pre {
			n += copy(unpacked[n:], s[pre-nz:dpw-pre-n+(pre-nz)])
		} else {
			n += copy(unpacked[n:], s[:dpw-pre-n])
		}
	}

	if len(packed) == WordSize {
		return n, nil
	}

	// Process until the second last word.
	for i := WordSize; i < len(packed)-WordSize; i += WordSize {
		s := strconv.FormatUint(binary.LittleEndian.Uint64(packed[i:]), radix)
		nz := dpw - len(s)
		if nz < 0 {
			return n, fmt.Errorf("%w: word = %16x, unpacked = %s", ErrInvalidWord,
				packed[i:i+WordSize], s)
		}
		n += copyWithZero(unpacked[n:], s, nz)
	}

	// Process the last word with post.
	s = strconv.FormatUint(binary.LittleEndian.Uint64(packed[len(packed)-WordSize:]), radix)
	nz = dpw - len(s)
	if nz < 0 {
		return n, fmt.Errorf("%w: word = %16x, unpacked = %s", ErrInvalidWord,
			packed[len(packed)-WordSize:], s)
	}
	n += copy(unpacked[n:], zeros[:nz])
	if n < len(unpacked) {
		n += copy(unpacked[n:], s)
	}
	return n, nil
}