// Copyright 2026 International Digital Economy Academy
//
// Licensed 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.
///|
/// A buffered writer with a fixed size buffer that wraps around a normal writer.
/// Data will be buffered,
/// instead of being comitted to the underlying writer immediately,
/// unless the buffer is full or explicit flush is requested.
/// Buffering can can improve performance for network connections etc.
/// where small writes are expensive.
///
/// Always remember to call `flush` before writing directly to the underlying writer.
/// Otherwise some data may remain uncommitted.
struct BufferedWriter[W] {
writer : W
buf : FixedArray[Byte]
mut len : Int32
ctrl : BinaryWriterController
}
///|
/// Create a buffered writer with fixed buffer size `size`.
pub fn[W] BufferedWriter::new(
writer : W,
size~ : Int32 = 1024,
) -> BufferedWriter[W] {
{
writer,
buf: FixedArray::make(size, 0),
len: 0,
ctrl: BinaryWriterController(),
}
}
///|
/// Return the internal buffer size of a buffered writer.
pub fn[W] BufferedWriter::capacity(self : BufferedWriter[W]) -> Int32 {
self.buf.length()
}
///|
/// Flush all buffered data and commit them to the underlying writer.
pub async fn[W : BinaryWriter] BufferedWriter::flush(
self : BufferedWriter[W],
) -> Unit {
if self.len > 0 {
self.writer.write(self.buf.unsafe_reinterpret_as_bytes()[:self.len])
self.len = 0
}
}
///|
pub impl[W : BinaryWriter] BinaryWriter for BufferedWriter[W]
///|
impl[W : BinaryWriter] BinaryWriterImpl for BufferedWriter[W] with fn raw_write_impl(
self,
buf,
offset~,
len~,
) {
if self.len >= self.buf.length() {
self.flush()
}
let len = @cmp.minimum(len, self.buf.length() - self.len)
self.buf.blit_from_bytes(self.len, buf, offset, len)
self.len += len
len
}
///|
impl[W : BinaryWriter] BinaryWriterImpl for BufferedWriter[W] with fn get_controller(
self,
) {
self.ctrl
}
///|
pub extend BufferedWriter with BinaryWriter::{write, write_reader}