    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019
    020package org.apache.commons.compress.compressors.brotli;
    021
    022import java.io.IOException;
    023import java.io.InputStream;
    024
    025import org.apache.commons.compress.compressors.CompressorInputStream;
    026import org.apache.commons.compress.utils.InputStreamStatistics;
    027import org.apache.commons.io.IOUtils;
    028import org.apache.commons.io.input.BoundedInputStream;
    029import org.brotli.dec.BrotliInputStream;
    030
    031/**
    032 * {@link CompressorInputStream} implementation to decode Brotli encoded stream. Library relies on <a href="https://github.com/google/brotli">Google brotli</a>
    033 *
    034 * @since 1.14
    035 */
    036public class BrotliCompressorInputStream extends CompressorInputStream implements InputStreamStatistics {
    037
    038    private final BoundedInputStream countingInputStream;
    039    private final BrotliInputStream brotliInputStream;
    040
    041    /**
    042     * Construct a new instance.
    043     *
    044     * @param inputStream underlying data source.
    045     * @throws IOException in case of corrupted data or source stream problems.
    046     */
    047    public BrotliCompressorInputStream(final InputStream inputStream) throws IOException {
    048        brotliInputStream = new BrotliInputStream(countingInputStream = BoundedInputStream.builder().setInputStream(inputStream).get());
    049    }
    050
    051    @Override
    052    public int available() throws IOException {
    053        return brotliInputStream.available();
    054    }
    055
    056    @Override
    057    public void close() throws IOException {
    058        brotliInputStream.close();
    059    }
    060
    061    /**
    062     * @since 1.17
    063     */
    064    @Override
    065    public long getCompressedCount() {
    066        return countingInputStream.getCount();
    067    }
    068
    069    @Override
    070    public synchronized void mark(final int readLimit) {
    071        brotliInputStream.mark(readLimit);
    072    }
    073
    074    @Override
    075    public boolean markSupported() {
    076        return brotliInputStream.markSupported();
    077    }
    078
    079    @Override
    080    public int read() throws IOException {
    081        final int ret = brotliInputStream.read();
    082        count(ret == -1 ? 0 : 1);
    083        return ret;
    084    }
    085
    086    @Override
    087    public int read(final byte[] b) throws IOException {
    088        return brotliInputStream.read(b);
    089    }
    090
    091    @Override
    092    public int read(final byte[] buf, final int off, final int len) throws IOException {
    093        final int ret = brotliInputStream.read(buf, off, len);
    094        count(ret);
    095        return ret;
    096    }
    097
    098    @Override
    099    public synchronized void reset() throws IOException {
    100        brotliInputStream.reset();
    101    }
    102
    103    @Override
    104    public long skip(final long n) throws IOException {
    105        return IOUtils.skip(brotliInputStream, n);
    106    }
    107
    108    @Override
    109    public String toString() {
    110        return brotliInputStream.toString();
    111    }
    112}