///|
fn pdf_decode_png_current(
  data : BytesView,
  row_start : Int,
  available : Int,
  index : Int,
) -> Int {
  if index < available {
    data[row_start + index].to_int()
  } else {
    0
  }
}

///|
fn pdf_decode_png_decoded_length(data : BytesView, scanline_width : Int) -> Int {
  let mut rows = 0
  let mut index = 0
  while index < data.length() {
    rows += 1
    index += 1
    let available = if index + scanline_width > data.length() {
      data.length() - index
    } else {
      scanline_width
    }
    index += available
  }
  rows * scanline_width
}

///|
fn pdf_decode_png_push_scanline(
  output : Array[Byte],
  position : Int,
  predictor : Int,
  prior_decoded : ArrayView[Int],
  decoded : Array[Int],
  data : BytesView,
  row_start : Int,
  available : Int,
  bytes_per_pixel : Int,
) -> Int raise @core.PdfError {
  let scanline_width = decoded.length()
  let mut output_position = position
  match predictor {
    0 =>
      for i in 0..
      for i in 0..
      for i in 0..
      for i in 0..
      for i in 0.. raise PredictorNotSupported(predictor)
  }
  output_position
}

///|
fn pdf_decode_png_predictor(
  colors : Int,
  bits_per_component : Int,
  columns : Int,
  data : BytesView,
) -> @core.PdfBytes raise @core.PdfError {
  let scanline_width = pdf_predictor_scanline_width(
    colors, bits_per_component, columns,
  )
  let bytes_per_pixel = pdf_predictor_bytes_per_pixel(
    colors, bits_per_component,
  )
  let output = Array::make(
    pdf_decode_png_decoded_length(data, scanline_width),
    b'\x00',
  )
  let mut position = 0
  let mut prior_decoded : Array[Int] = [ for _ in 0.. 0 ]
  let mut decoded : Array[Int] = [ for _ in 0.. 0 ]
  let mut index = 0
  while index < data.length() {
    let predictor = data[index].to_int()
    index += 1
    let available = if index + scanline_width > data.length() {
      data.length() - index
    } else {
      scanline_width
    }
    let row_start = index
    index += available
    position = pdf_decode_png_push_scanline(
      output, position, predictor, prior_decoded, decoded, data, row_start, available,
      bytes_per_pixel,
    )
    let previous = prior_decoded
    prior_decoded = decoded
    decoded = previous
  }
  Bytes::from_array(output[:position])
}