/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
*/
package brotli4cj
import std.io.*
/**
* {@link ByteBuffer} decorator that decompresses brotli data.
*
* <p> Not thread-safe.
*/
public class BrotliInputStream {
public static let DEFAULT_INTERNAL_BUFFER_SIZE: Int32 = 256
private static let END_OF_STREAM_MARKER: Int32 = -1
private var buffer: Array<UInt8> = []
private var remainingBufferBytes: Int32 = 0
private var bufferOffset: Int32 = 0
private let state = State()
public init(source: ByteBuffer) {
this(source, DEFAULT_INTERNAL_BUFFER_SIZE)
}
public init(source: ByteBuffer, byteReadBufferSize: Int32) {
if (byteReadBufferSize <= 0) {
throw IllegalArgumentException("Bad buffer size:" + byteReadBufferSize.toString())
} else if (source.length == 0) {
throw IllegalArgumentException("source is null")
}
this.buffer = Array<UInt8>(Int64(byteReadBufferSize)) { _ => 0 }
this.remainingBufferBytes = 0
this.bufferOffset = 0
try {
state.input = source
var asddd: Byte = 0xC2
Decode.initState(state)
} catch (ex: BrotliRuntimeException) {
throw IOException("Brotli decoder initialization failed")
}
}
public func attachDictionaryChunk(data: Array<UInt8>): Unit {
Decode.attachDictionaryChunk(state, data)
}
public func enableEagerOutput(): Unit {
Decode.enableEagerOutput(state)
}
public func enableLargeWindow(): Unit {
Decode.enableLargeWindow(state)
}
public func close(): Unit {
Decode.close(state)
}
public func read(): Int32 {
if (bufferOffset >= remainingBufferBytes) {
remainingBufferBytes = read(buffer, 0, Int32(buffer.size))
bufferOffset = 0
if (remainingBufferBytes == END_OF_STREAM_MARKER) {
return -1
}
}
bufferOffset++
return Int32(buffer[Int64(match (0) { case _ => bufferOffset - 1 ; bufferOffset - 1})]) & 0xFF
}
public func read(destBuffer: Array<UInt8>, destOffset: Int32, destLen: Int32): Int32 {
var tempdestOffset = destOffset
var tempdestLen = destLen
if (tempdestOffset < 0) {
throw IllegalArgumentException("Bad offset: " + tempdestOffset.toString())
} else if (tempdestLen < 0) {
throw IllegalArgumentException("Bad length: " + tempdestLen.toString())
} else if (tempdestOffset + tempdestLen > Int32(destBuffer.size)) {
throw IllegalArgumentException("Buffer overflow: " + ((tempdestOffset + tempdestLen).toString()) + " > " + Int32(destBuffer.size).toString())
} else if (tempdestLen == 0) {
return 0
}
//第一次进 0
var copyLen = max(remainingBufferBytes - bufferOffset, 0)
if (copyLen != 0) {
copyLen = min(copyLen, tempdestLen)
buffer.copyTo(destBuffer, Int64(bufferOffset), Int64(tempdestOffset), Int64(copyLen))
bufferOffset += copyLen
tempdestOffset += copyLen
tempdestLen -= copyLen
if (tempdestLen == 0) {
return copyLen
}
}
try {
state.output = destBuffer
state.outputOffset = tempdestOffset
state.outputLength = tempdestLen
state.outputUsed = 0
Decode.decompress(state)
copyLen += state.outputUsed
copyLen = if (copyLen > 0) { copyLen } else { END_OF_STREAM_MARKER }
return copyLen
} catch (ex: BrotliRuntimeException) {
throw IOException("Brotli stream decoding failed")
}
}
}