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

///|
fn pdf_decode_png_decoded_length(
  data : BytesView,
  scanline_width : Int32,
) -> Int32 {
  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 : Int32,
  predictor : Int32,
  prior_decoded : ArrayView[Int32],
  decoded : Array[Int32],
  data : BytesView,
  row_start : Int32,
  available : Int32,
  bytes_per_pixel : Int32,
) -> Int32 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 : Int32,
  bits_per_component : Int32,
  columns : Int32,
  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[Int32] = [ for _ in 0.. 0 ]
  let mut decoded : Array[Int32] = [ 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])
}