// Copyright 2026 Noverberrain.
// SPDX-License-Identifier: Apache-2.0

///|
priv struct RowsReader {
  data : BytesView
  file_offset : UInt64
  mut position : Int32
}

///|
fn RowsReader::remaining(self : RowsReader) -> Int32 {
  self.data.length() - self.position
}

///|
fn RowsReader::invalid(self : RowsReader, reason : String) -> DecodeError {
  InvalidRowsEvent(
    file_offset=self.file_offset,
    body_offset=self.position,
    reason~,
  )
}

///|
fn RowsReader::take(
  self : RowsReader,
  length : Int32,
) -> BytesView raise DecodeError {
  guard length >= 0 && length <= self.remaining() else {
    raise self.invalid("truncated ROWS field")
  }
  let start = self.position
  self.position += length
  self.data[start:self.position]
}

///|
fn RowsReader::uint_le(
  self : RowsReader,
  width : Int32,
) -> UInt64 raise DecodeError {
  let bytes = self.take(width)
  let mut value = 0UL
  for i in 0.. UInt64 raise DecodeError {
  match self.take(1)[0] {
    0..<=250 as value => value.to_uint().to_uint64()
    252 => self.uint_le(2)
    253 => self.uint_le(3)
    254 => self.uint_le(8)
    _ => raise self.invalid("NULL or reserved column-count marker")
  }
}

///|
fn RowsReader::image(
  self : RowsReader,
  table : TableMap,
  present : BytesView,
  signs : ReadOnlyArray[Bool?],
  max_bytes : Int32,
) -> RowImage raise DecodeError {
  let image = table.decode_row_image(
    self.data[self.position:],
    columns_present=present,
    integer_unsigned=signs,
    file_offset=self.file_offset +
      19 +
      self.position.reinterpret_as_uint().to_uint64(),
    max_bytes~,
  )
  self.position += image.bytes_read
  image
}