2430eacc创建于 2024年11月20日历史提交
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
 */
package zip4cj.io.inputstream

public class ZipEntryInputStream <: InputStream & Resource {
    private static let MAX_RAW_READ_FULLY_RETRY_ATTEMPTS: Int64 = 15

    private var inputStream: InputStream
    private var numberOfBytesRead: Int64 = 0
    private var singleByteArray: Array<Byte> = [1]
    private var compressedSize: Int64
    var closed = false
    public init(inputStream: InputStream, compressedSize: Int64) {
        this.inputStream = inputStream
        this.compressedSize = compressedSize
    }

    public func read(b: Array<Byte>): Int64 {
        return read(b, 0, b.size)
    }

    func read(b: Array<Byte>, off: Int64, len: Int64): Int64 {
        var length = len
        if (compressedSize != -1) {
            if (numberOfBytesRead >= compressedSize) {
                return -1
            }
            if (length > compressedSize - numberOfBytesRead) {
                length = compressedSize - numberOfBytesRead
            }
        }
        var readLen: Int64 = inputStream.read(b[off..off + length]) //read(b, off, len)
        if (readLen > 0) {
            numberOfBytesRead += readLen
        }
        return readLen
    }

    public func readRawFully(b: Array<Byte>): Int64 {
        var readLen: Int64 = inputStream.read(b)

        if (readLen == -1) {
            throw ZipIOException("Unexpected EOF reached when trying to read stream")
        }

        if (readLen != b.size) {
            readLen = readUntilBufferIsFull(b, readLen)

            if (readLen != b.size) {
                throw ZipIOException("Cannot read fully into byte buffer")
            }
        }

        return readLen
    }

    private func readUntilBufferIsFull(b: Array<Byte>, readLength: Int64): Int64 {
        var readlength = readLength
        var remainingLength: Int64 = b.size - readlength
        var loopReadLength = 0
        var retryAttempt = 0

        while (readlength < b.size && loopReadLength != -1 && retryAttempt < MAX_RAW_READ_FULLY_RETRY_ATTEMPTS) {
            loopReadLength += inputStream.read(b) //read(b, readLength, remainingLength)

            if (loopReadLength > 0) {
                readlength += loopReadLength
                remainingLength -= loopReadLength
            }

            retryAttempt++
        }

        return readlength
    }

    public func close(): Unit {
        match ((this.inputStream as Resource)) {
            case Some(v) => v.close()
            case _ => ()
        }
        closed = true
    }

    public func isClosed(): Bool {
        closed
    }

    public func getNumberOfBytesRead(): Int64 {
        return numberOfBytesRead
    }
}