// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package zstd

import (
	
)

// readLiterals reads and decompresses the literals from data at off.
// The literals are appended to outbuf, which is returned.
// Also returns the new input offset. RFC 3.1.1.3.1.
func ( *Reader) ( block,  int,  []byte) (int, []byte, error) {
	if  >= len() {
		return 0, nil, .makeEOFError()
	}

	// Literals section header. RFC 3.1.1.3.1.1.
	 := []
	++

	if (&3) == 0 || (&3) == 1 {
		return .readRawRLELiterals(, , , )
	} else {
		return .readHuffLiterals(, , , )
	}
}

// readRawRLELiterals reads and decompresses a Raw_Literals_Block or
// a RLE_Literals_Block. RFC 3.1.1.3.1.1.
func ( *Reader) ( block,  int,  byte,  []byte) (int, []byte, error) {
	 := ( & 3) == 0

	var  int
	switch ( >> 2) & 3 {
	case 0, 2:
		 = int( >> 3)
	case 1:
		if  >= len() {
			return 0, nil, .makeEOFError()
		}
		 = int(>>4) + (int([]) << 4)
		++
	case 3:
		if +1 >= len() {
			return 0, nil, .makeEOFError()
		}
		 = int(>>4) + (int([]) << 4) + (int([+1]) << 12)
		 += 2
	}

	// We are going to use the entire literal block in the output.
	// The maximum size of one decompressed block is 128K,
	// so we can't have more literals than that.
	if  > 128<<10 {
		return 0, nil, .makeError(, "literal size too large")
	}

	if  {
		// RFC 3.1.1.3.1.2.
		if + > len() {
			return 0, nil, .makeError(, "raw literal size too large")
		}
		 = append(, [:+]...)
		 += 
	} else {
		// RFC 3.1.1.3.1.3.
		if  >= len() {
			return 0, nil, .makeError(, "RLE literal missing")
		}
		 := []
		++
		for  := 0;  < ; ++ {
			 = append(, )
		}
	}

	return , , nil
}

// readHuffLiterals reads and decompresses a Compressed_Literals_Block or
// a Treeless_Literals_Block. RFC 3.1.1.3.1.4.
func ( *Reader) ( block,  int,  byte,  []byte) (int, []byte, error) {
	var (
		 int
		  int
		         int
	)
	switch ( >> 2) & 3 {
	case 0, 1:
		if +1 >= len() {
			return 0, nil, .makeEOFError()
		}
		 = (int() >> 4) | ((int([]) & 0x3f) << 4)
		 = (int([]) >> 6) | (int([+1]) << 2)
		 += 2
		if (( >> 2) & 3) == 0 {
			 = 1
		} else {
			 = 4
		}
	case 2:
		if +2 >= len() {
			return 0, nil, .makeEOFError()
		}
		 = (int() >> 4) | (int([]) << 4) | ((int([+1]) & 3) << 12)
		 = (int([+1]) >> 2) | (int([+2]) << 6)
		 += 3
		 = 4
	case 3:
		if +3 >= len() {
			return 0, nil, .makeEOFError()
		}
		 = (int() >> 4) | (int([]) << 4) | ((int([+1]) & 0x3f) << 12)
		 = (int([+1]) >> 6) | (int([+2]) << 2) | (int([+3]) << 10)
		 += 4
		 = 4
	}

	// We are going to use the entire literal block in the output.
	// The maximum size of one decompressed block is 128K,
	// so we can't have more literals than that.
	if  > 128<<10 {
		return 0, nil, .makeError(, "literal size too large")
	}

	 :=  + 
	if  > len() ||  < 0 {
		return 0, nil, .makeEOFError()
	}

	 := 
	if ( & 3) == 2 {
		// Compressed_Literals_Block.
		// Read new huffman tree.

		if len(.huffmanTable) < 1<<maxHuffmanBits {
			.huffmanTable = make([]uint16, 1<<maxHuffmanBits)
		}

		, ,  := .readHuff(, , .huffmanTable)
		if  != nil {
			return 0, nil, 
		}
		.huffmanTableBits = 

		if  < - {
			return 0, nil, .makeError(, "Huffman table too big")
		}
		 -=  - 
		 = 
	} else {
		// Treeless_Literals_Block
		// Reuse previous Huffman tree.
		if .huffmanTableBits == 0 {
			return 0, nil, .makeError(, "missing literals Huffman tree")
		}
	}

	// Decompress compressedSize bytes of data at off using the
	// Huffman tree.

	var  error
	if  == 1 {
		,  = .readLiteralsOneStream(, , , , )
	} else {
		,  = .readLiteralsFourStreams(, , , , )
	}

	if  != nil {
		return 0, nil, 
	}

	return , , nil
}

// readLiteralsOneStream reads a single stream of compressed literals.
func ( *Reader) ( block, , ,  int,  []byte) ([]byte, error) {
	// We let the reverse bit reader read earlier bytes,
	// because the Huffman table ignores bits that it doesn't need.
	,  := .makeReverseBitReader(, +-1, -2)
	if  != nil {
		return nil, 
	}

	 := .huffmanTable
	 := uint32(.huffmanTableBits)
	 := (uint32(1) << ) - 1

	for  := 0;  < ; ++ {
		if !.fetch(uint8()) {
			return nil, .makeError("literals Huffman stream out of bits")
		}

		var  uint16
		 := (.bits >> (.cnt - )) & 
		 = []
		 = append(, byte(>>8))
		.cnt -= uint32( & 0xff)
	}

	return , nil
}

// readLiteralsFourStreams reads four interleaved streams of
// compressed literals.
func ( *Reader) ( block, , ,  int,  []byte) ([]byte, error) {
	// Read the jump table to find out where the streams are.
	// RFC 3.1.1.3.1.6.
	if +5 >= len() {
		return nil, .makeEOFError()
	}
	if  < 6 {
		return nil, .makeError(, "total streams size too small for jump table")
	}
	// RFC 3.1.1.3.1.6.
	// "The decompressed size of each stream is equal to (Regenerated_Size+3)/4,
	// except for the last stream, which may be up to 3 bytes smaller,
	// to reach a total decompressed size as specified in Regenerated_Size."
	 := ( + 3) / 4
	if  < *3 {
		return nil, .makeError(, "regenerated size too small to decode streams")
	}

	 := binary.LittleEndian.Uint16([:])
	 := binary.LittleEndian.Uint16([+2:])
	 := binary.LittleEndian.Uint16([+4:])
	 += 6

	 := uint64() + uint64() + uint64()
	if  > uint64()-6 {
		return nil, .makeEOFError()
	}
	 := uint32() - 6 - uint32()

	--
	 :=  + int()
	 :=  + 1

	 :=  + int()
	 :=  + 1

	 :=  + int()
	 :=  + 1

	 :=  + int()
	 :=  + 1

	// We let the reverse bit readers read earlier bytes,
	// because the Huffman tables ignore bits that they don't need.

	,  := .makeReverseBitReader(, , -2)
	if  != nil {
		return nil, 
	}

	,  := .makeReverseBitReader(, , -2)
	if  != nil {
		return nil, 
	}

	,  := .makeReverseBitReader(, , -2)
	if  != nil {
		return nil, 
	}

	,  := .makeReverseBitReader(, , -2)
	if  != nil {
		return nil, 
	}

	 := len()
	 :=  + 
	 :=  + 
	 :=  + 

	 :=  - *3

	 = append(, make([]byte, )...)

	 := .huffmanTable
	 := uint32(.huffmanTableBits)
	 := (uint32(1) << ) - 1

	for  := 0;  < ; ++ {
		 :=  < 

		 := func( *reverseBitReader) (uint16, error) {
			if !.fetch(uint8()) {
				return 0, .makeError("literals Huffman stream out of bits")
			}
			 := (.bits >> (.cnt - )) & 
			return [], nil
		}

		,  := (&)
		if  != nil {
			return nil, 
		}

		,  := (&)
		if  != nil {
			return nil, 
		}

		,  := (&)
		if  != nil {
			return nil, 
		}

		if  {
			,  := (&)
			if  != nil {
				return nil, 
			}
			[] = byte( >> 8)
			++
			.cnt -= uint32( & 0xff)
		}

		[] = byte( >> 8)
		++
		.cnt -= uint32( & 0xff)

		[] = byte( >> 8)
		++
		.cnt -= uint32( & 0xff)

		[] = byte( >> 8)
		++
		.cnt -= uint32( & 0xff)
	}

	return , nil
}