package lz4

import (
	
	
	

	
	
)

//go:generate go run golang.org/x/tools/cmd/stringer -type=BlockSize,CompressionLevel -output options_gen.go

type (
	applier interface {
		Apply(...Option) error
		private()
	}
	// Option defines the parameters to setup an LZ4 Writer or Reader.
	Option func(applier) error
)

// String returns a string representation of the option with its parameter(s).
func ( Option) () string {
	return (nil).Error()
}

// Default options.
var (
	DefaultBlockSizeOption = BlockSizeOption(Block4Mb)
	DefaultChecksumOption  = ChecksumOption(true)
	DefaultConcurrency     = ConcurrencyOption(1)
	defaultOnBlockDone     = OnBlockDoneOption(nil)
)

const (
	Block64Kb BlockSize = 1 << (16 + iota*2)
	Block256Kb
	Block1Mb
	Block4Mb
)

// BlockSizeIndex defines the size of the blocks to be compressed.
type BlockSize uint32

// BlockSizeOption defines the maximum size of compressed blocks (default=Block4Mb).
func ( BlockSize) Option {
	return func( applier) error {
		switch w := .(type) {
		case nil:
			 := fmt.Sprintf("BlockSizeOption(%s)", )
			return lz4errors.Error()
		case *Writer:
			 := uint32()
			if !lz4block.IsValid() {
				return fmt.Errorf("%w: %d", lz4errors.ErrOptionInvalidBlockSize, )
			}
			.frame.Descriptor.Flags.BlockSizeIndexSet(lz4block.Index())
			return nil
		case *CompressingReader:
			 := uint32()
			if !lz4block.IsValid() {
				return fmt.Errorf("%w: %d", lz4errors.ErrOptionInvalidBlockSize, )
			}
			.frame.Descriptor.Flags.BlockSizeIndexSet(lz4block.Index())
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}

// BlockChecksumOption enables or disables block checksum (default=false).
func ( bool) Option {
	return func( applier) error {
		switch w := .(type) {
		case nil:
			 := fmt.Sprintf("BlockChecksumOption(%v)", )
			return lz4errors.Error()
		case *Writer:
			.frame.Descriptor.Flags.BlockChecksumSet()
			return nil
		case *CompressingReader:
			.frame.Descriptor.Flags.BlockChecksumSet()
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}

// ChecksumOption enables/disables all blocks or content checksum (default=true).
func ( bool) Option {
	return func( applier) error {
		switch w := .(type) {
		case nil:
			 := fmt.Sprintf("ChecksumOption(%v)", )
			return lz4errors.Error()
		case *Writer:
			.frame.Descriptor.Flags.ContentChecksumSet()
			return nil
		case *CompressingReader:
			.frame.Descriptor.Flags.ContentChecksumSet()
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}

// SizeOption sets the size of the original uncompressed data (default=0). It is useful to know the size of the
// whole uncompressed data stream.
func ( uint64) Option {
	return func( applier) error {
		switch w := .(type) {
		case nil:
			 := fmt.Sprintf("SizeOption(%d)", )
			return lz4errors.Error()
		case *Writer:
			.frame.Descriptor.Flags.SizeSet( > 0)
			.frame.Descriptor.ContentSize = 
			return nil
		case *CompressingReader:
			.frame.Descriptor.Flags.SizeSet( > 0)
			.frame.Descriptor.ContentSize = 
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}

// ConcurrencyOption sets the number of go routines used for compression.
// If n <= 0, then the output of runtime.GOMAXPROCS(0) is used.
func ( int) Option {
	if  <= 0 {
		 = runtime.GOMAXPROCS(0)
	}
	return func( applier) error {
		switch rw := .(type) {
		case nil:
			 := fmt.Sprintf("ConcurrencyOption(%d)", )
			return lz4errors.Error()
		case *Writer:
			.num = 
			return nil
		case *Reader:
			.num = 
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}

// CompressionLevel defines the level of compression to use. The higher the better, but slower, compression.
type CompressionLevel uint32

const (
	Fast   CompressionLevel = 0
	Level1 CompressionLevel = 1 << (8 + iota)
	Level2
	Level3
	Level4
	Level5
	Level6
	Level7
	Level8
	Level9
)

// CompressionLevelOption defines the compression level (default=Fast).
func ( CompressionLevel) Option {
	return func( applier) error {
		switch w := .(type) {
		case nil:
			 := fmt.Sprintf("CompressionLevelOption(%s)", )
			return lz4errors.Error()
		case *Writer:
			switch  {
			case Fast, Level1, Level2, Level3, Level4, Level5, Level6, Level7, Level8, Level9:
			default:
				return fmt.Errorf("%w: %d", lz4errors.ErrOptionInvalidCompressionLevel, )
			}
			.level = lz4block.CompressionLevel()
			return nil
		case *CompressingReader:
			switch  {
			case Fast, Level1, Level2, Level3, Level4, Level5, Level6, Level7, Level8, Level9:
			default:
				return fmt.Errorf("%w: %d", lz4errors.ErrOptionInvalidCompressionLevel, )
			}
			.level = lz4block.CompressionLevel()
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}

func onBlockDone(int) {}

// OnBlockDoneOption is triggered when a block has been processed. For a Writer, it is when is has been compressed,
// for a Reader, it is when it has been uncompressed.
func ( func( int)) Option {
	if  == nil {
		 = onBlockDone
	}
	return func( applier) error {
		switch rw := .(type) {
		case nil:
			 := fmt.Sprintf("OnBlockDoneOption(%s)", reflect.TypeOf().String())
			return lz4errors.Error()
		case *Writer:
			.handler = 
			return nil
		case *Reader:
			.handler = 
			return nil
		case *CompressingReader:
			.handler = 
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}

// LegacyOption provides support for writing LZ4 frames in the legacy format.
//
// See https://github.com/lz4/lz4/blob/dev/doc/lz4_Frame_format.md#legacy-frame.
//
// NB. compressed Linux kernel images use a tweaked LZ4 legacy format where
// the compressed stream is followed by the original (uncompressed) size of
// the kernel (https://events.static.linuxfound.org/sites/events/files/lcjpcojp13_klee.pdf).
// This is also supported as a special case.
func ( bool) Option {
	return func( applier) error {
		switch rw := .(type) {
		case nil:
			 := fmt.Sprintf("LegacyOption(%v)", )
			return lz4errors.Error()
		case *Writer:
			.legacy = 
			return nil
		}
		return lz4errors.ErrOptionNotApplicable
	}
}