// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ipc

import (
	

	
	
	
	
	
)

type compressor interface {
	MaxCompressedLen(n int) int
	Reset(io.Writer)
	io.WriteCloser
	Type() flatbuf.CompressionType
}

type lz4Compressor struct {
	*lz4.Writer
}

func (lz4Compressor) ( int) int {
	return lz4.CompressBlockBound()
}

func (lz4Compressor) () flatbuf.CompressionType {
	return flatbuf.CompressionTypeLZ4_FRAME
}

type zstdCompressor struct {
	*zstd.Encoder
}

// from zstd.h, ZSTD_COMPRESSBOUND
func (zstdCompressor) ( int) int {
	debug.Assert( >= 0, "MaxCompressedLen called with len less than 0")
	 := uint((uint(128<<10) - uint()) >> 11)
	if  >= (128 << 10) {
		 = 0
	}
	return int(uint(+(>>8)) + )
}

func (zstdCompressor) () flatbuf.CompressionType {
	return flatbuf.CompressionTypeZSTD
}

func getCompressor( flatbuf.CompressionType) compressor {
	switch  {
	case flatbuf.CompressionTypeLZ4_FRAME:
		 := lz4.NewWriter(nil)
		// options here chosen in order to match the C++ implementation
		.Apply(lz4.ChecksumOption(false), lz4.BlockSizeOption(lz4.Block64Kb))
		return &lz4Compressor{}
	case flatbuf.CompressionTypeZSTD:
		,  := zstd.NewWriter(nil)
		if  != nil {
			panic()
		}
		return zstdCompressor{}
	}
	return nil
}

type decompressor interface {
	io.Reader
	Reset(io.Reader)
	Close()
}

type zstdDecompressor struct {
	*zstd.Decoder
}

func ( *zstdDecompressor) ( io.Reader) {
	if  := .Decoder.Reset();  != nil {
		panic()
	}
}

func ( *zstdDecompressor) () {
	.Decoder.Close()
}

type lz4Decompressor struct {
	*lz4.Reader
}

func ( *lz4Decompressor) () {
	.Reset(nil)
}

func getDecompressor( flatbuf.CompressionType) decompressor {
	switch  {
	case flatbuf.CompressionTypeLZ4_FRAME:
		return &lz4Decompressor{lz4.NewReader(nil)}
	case flatbuf.CompressionTypeZSTD:
		,  := zstd.NewReader(nil)
		if  != nil {
			panic()
		}
		return &zstdDecompressor{}
	}
	return nil
}

type bufferWriter struct {
	buf *memory.Buffer
	pos int
}

func ( *bufferWriter) ( []byte) ( int,  error) {
	if .pos+len() >= .buf.Cap() {
		.buf.Reserve(.pos + len())
	}
	 = copy(.buf.Buf()[.pos:], )
	.pos += 
	return
}