///|
fn pdf_run_length_flush_literal(
  output : Array[Byte],
  position : Int,
  data : BytesView,
  start : Int,
  length : Int,
) -> Int {
  let mut current = position
  if length > 0 {
    output[current] = (length - 1).to_byte()
    current += 1
    for i in 0.. PdfBytes {
  let output = Array::make(
    data.length() + (data.length() + 127) / 128 + 1,
    b'\x00',
  )
  let mut position = 0
  let mut literal_start = 0
  let mut literal_length = 0
  let mut index = 0
  while index < data.length() {
    let value = data[index]
    let mut run_length = 1
    while index + run_length < data.length() &&
          data[index + run_length] == value &&
          run_length < 128 {
      run_length += 1
    }
    if run_length >= 3 {
      position = pdf_run_length_flush_literal(
        output, position, data, literal_start, literal_length,
      )
      literal_length = 0
      output[position] = (257 - run_length).to_byte()
      output[position + 1] = value
      position += 2
      index += run_length
    } else {
      if literal_length == 0 {
        literal_start = index
      }
      if literal_length + run_length > 128 {
        position = pdf_run_length_flush_literal(
          output, position, data, literal_start, literal_length,
        )
        literal_start = index
        literal_length = 0
      }
      literal_length += run_length
      index += run_length
    }
  }
  position = pdf_run_length_flush_literal(
    output, position, data, literal_start, literal_length,
  )
  output[position] = 128
  Bytes::from_array(output[:position + 1])
}

///|
/// Owned-byte wrapper for `pdf_run_length_encode_view`.
pub fn pdf_run_length_encode(data : PdfBytes) -> PdfBytes {
  pdf_run_length_encode_view(data)
}

///|
fn pdf_run_length_decoded_length(data : BytesView) -> Int {
  let mut length = 0
  let mut index = 0
  let mut done = false
  while !done && index < data.length() {
    let control = data[index].to_int()
    index += 1
    if control < 128 {
      let wanted = control + 1
      let available = if index + wanted > data.length() {
        data.length() - index
      } else {
        wanted
      }
      length += available
      index += available
    } else if control > 128 {
      if index < data.length() {
        length += 257 - control
        index += 1
      } else {
        done = true
      }
    } else {
      done = true
    }
  }
  length
}

///|
/// Decode PDF RunLengthDecode data.
///
/// Decoding stops at the `128` end marker or end of input. Truncated trailing
/// runs are decoded as far as bytes are available, matching the tolerant reader
/// behavior used by CamlPDF.
pub fn pdf_run_length_decode_view(data : BytesView) -> PdfBytes {
  let output = Array::make(pdf_run_length_decoded_length(data), b'\x00')
  let mut position = 0
  let mut index = 0
  let mut done = false
  while !done && index < data.length() {
    let control = data[index].to_int()
    index += 1
    if control < 128 {
      let wanted = control + 1
      let available = if index + wanted > data.length() {
        data.length() - index
      } else {
        wanted
      }
      for i in 0.. 128 {
      if index < data.length() {
        let value = data[index]
        index += 1
        for _ in 0..<(257 - control) {
          output[position] = value
          position += 1
        }
      } else {
        done = true
      }
    } else {
      done = true
    }
  }
  Bytes::from_array(output[:position])
}

///|
/// Owned-byte wrapper for `pdf_run_length_decode_view`.
pub fn pdf_run_length_decode(data : PdfBytes) -> PdfBytes {
  pdf_run_length_decode_view(data)
}