Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

io/buffered/writer.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature io.buffered.writer
#
# -----------------------------------------------------------------------


# buffered.writer effect allows buffered writing
# by using the given Write_Handler
#
# note: anything in the buffer when effect is uninstalled will be discarded.
#
public writer(wh Write_Handler) : effect
is

  buf_size
    # NYI: UNDER DEVELOPMENT: does not work yet, post condition for field
    # post
    #   debug: buf_size > 0
    #   debug: buf_size % os.page_size.as_i32 = 0
  := io.buffer_size.as_i32


  # circular buffer backing this writer
  #
  buffer := (LM.Circular_Buffer u8).new buf_size.as_i64 0



  # finally
  # i.e. flush all unwritten bytes
  #
  public redef finally unit =>
    match flush
      e error =>
        fuzion.runtime.fault.cause ("{writer.this.type.name}.finally", e.msg)
      unit =>



  # flush the buffer, that is, write out everything that is still
  # in the buffer
  #
  # note that flush is also called automatically
  # when the effect is deinstated
  #
  public flush outcome unit =>
    if buffer.buffered = 0
      unit
    else
      n := buffer.buffered # we are expecting to write this number of bytes
      wh.write (buffer.flush n)


  # buffered writing of the given byte
  #
  public write_byte (b u8) outcome unit =>
    write [b]


  # helper type for write result
  #
  private:public write_result(public bytes_written i32, public error outcome unit) is


    # was writing successful?
    #
    public ok bool => error.ok


  # buffered writing of the given array
  #
  public write (data Sequence u8 | String) outcome unit =>
    write_detailed data
      .error


  # buffered writing of the given array, detailed result
  #
  public write_detailed (data Sequence u8 | String) write_result =>
    write_detailed
      (data ? s Sequence u8 => s.as_array | s String   => s.utf8.as_array)
      0


  # recursive helper for write_detailed
  #
  write_detailed (data Sequence u8, written i32) write_result =>
    # still fits into buffer, no need to flush yet
    if buffer.available.as_i32 >= data.count
      write_result written (buffer.enqueue data)
    else
      bfrd := buffer.buffered.as_i32
      match flush
        e error => write_result written e
        unit =>
          match wh.write (data.take buf_size)
            e error => write_result written+bfrd e
            unit => write_detailed (data.drop buf_size) written+bfrd+buf_size

last changed: 2026-03-05