// Copy up to length of bytes from input directly.
        // This is used for uncompressed block.
        public int CopyFrom(InputBuffer input, int length)
        {
            length = Math.Min(Math.Min(length, WindowSize - this.AvailableBytes), input.AvailableBytes);
            int copied;

            // We might need wrap around to copy all bytes.
            var tailLen = WindowSize - _end;
            if (length > tailLen)
            {
                // copy the first part     
                copied = input.CopyTo(_window, _end, tailLen);
                if (copied == tailLen)
                {
                    // only try to copy the second part if we have enough bytes in input
                    copied += input.CopyTo(_window, 0, length - tailLen);
                }
            }
            else
            {
                // only one copy is needed if there is no wrap around.
                copied = input.CopyTo(_window, _end, length);
            }

            _end = (_end + copied) & WindowMask;
            this.AvailableBytes += copied;
            return copied;
        }
        private IFileFormatReader _formatReader;  // class to decode header and footer (e.g. gzip)

        public Inflater()
        {
            _output = new OutputWindow();
            _input = new InputBuffer();

            _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements];
            _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements];
            Reset();
        }