///|
fn streaming_error(
  code : FirmwareErrorCode,
  message : String,
  line_index : Int,
  column_index : Int,
) -> FirmwareError {
  FirmwareError::new(
    code,
    message,
    SourcePosition::column(line_index, column_index),
  )
}

///|
fn join_stream_lines(lines : Array[String]) -> String {
  let mut text = ""
  for index, line in lines {
    if index > 0 {
      text = text + "\n"
    }
    text = text + line
  }
  text
}

///|
/// Decode caller-provided byte chunks without depending on chunk boundaries.
/// Input must be ASCII and each logical record is bounded independently.
pub fn decode_firmware_chunks(
  chunks : Array[Bytes],
  format? : FirmwareFormat? = None,
  policy? : OverlapPolicy = RejectOverlap,
  max_line_bytes? : Int = 1024,
) -> Result[ParsedFirmware, FirmwareError] {
  if max_line_bytes <= 0 {
    return Err(
      streaming_error(
        ImageInvalidRange,
        "maximum record length must be positive",
        0,
        0,
      ),
    )
  }
  let lines : Array[String] = []
  let mut current = ""
  let mut line_index = 0
  let mut previous_was_cr = false
  for chunk in chunks {
    for byte in chunk {
      let code = byte.to_int()
      if code == 13 {
        if current.length() == 0 {
          return Err(
            streaming_error(
              RecordEmpty,
              "firmware stream contains an empty record",
              line_index,
              0,
            ),
          )
        }
        lines.push(current)
        current = ""
        line_index = line_index + 1
        previous_was_cr = true
      } else if code == 10 {
        if previous_was_cr {
          previous_was_cr = false
        } else {
          if current.length() == 0 {
            return Err(
              streaming_error(
                RecordEmpty,
                "firmware stream contains an empty record",
                line_index,
                0,
              ),
            )
          }
          lines.push(current)
          current = ""
          line_index = line_index + 1
        }
      } else {
        previous_was_cr = false
        if code > 127 {
          return Err(
            streaming_error(
              RecordInvalidPrefix,
              "firmware stream must contain ASCII text",
              line_index,
              current.length(),
            ),
          )
        }
        if current.length() >= max_line_bytes {
          return Err(
            streaming_error(
              RecordTooLong,
              "firmware record exceeds the configured byte limit",
              line_index,
              current.length(),
            ),
          )
        }
        let character = match code.to_char() {
          Some(value) => value.to_string()
          None => ""
        }
        current = current + character
      }
    }
  }
  if current.length() > 0 {
    lines.push(current)
  }
  parse_firmware_image(join_stream_lines(lines), format~, policy~)
}