///|
/// Merges two Bytes objects into a single new Bytes object.
pub fn merge_bytes(b1 : Bytes, b2 : Bytes) -> Bytes {
  let len1 = b1.length()
  let len2 = b2.length()
  let arr = Array::make(len1 + len2, (0).to_byte())
  for i = 0; i < len1; i = i + 1 {
    arr[i] = b1[i]
  }
  for i = 0; i < len2; i = i + 1 {
    arr[len1 + i] = b2[i]
  }
  Bytes::from_array(arr)
}

///|
/// Container for a record retrieved from a WAL data file.
pub struct LogRecord {
  record : Record
  offset : Int
  size : Int
}

///|
/// Sequentially reads and parses all records from a WAL data file.
pub fn read_records_from_file(
  path : String,
) -> Array[LogRecord] raise MoonKVError {
  try {
    if @fs.path_exists(path) == false {
      return []
    }
    let file_bytes = @fs.read_file_to_bytes(path)
    let total_len = file_bytes.length()
    let mut offset = 0
    let records = Array::new()

    while offset < total_len {
      if total_len - offset < 28 {
        raise MoonKVError::CorruptedDatabase(
          "Incomplete record header at offset \{offset} in \{path}",
        )
      }

      // Decode header
      let header_arr = Array::make(28, (0).to_byte())
      for i = 0; i < 28; i = i + 1 {
        header_arr[i] = file_bytes[offset + i]
      }
      let header = Bytes::from_array(header_arr)
      let (_, _, _, key_sz, val_sz) = decode_header(header)

      if key_sz < 0 || val_sz < -1 {
        raise MoonKVError::CorruptedDatabase(
          "Invalid record sizes at offset \{offset} in \{path}",
        )
      }
      let val_len = if val_sz < 0 { 0 } else { val_sz }
      let remaining = total_len - offset - 28
      if key_sz > remaining || (!(val_sz < 0) && val_len > remaining - key_sz) {
        raise MoonKVError::CorruptedDatabase(
          "Record size exceeds file bounds at offset \{offset} in \{path}",
        )
      }
      let record_sz = 28 + key_sz + val_len

      if offset + record_sz > total_len {
        raise MoonKVError::CorruptedDatabase(
          "Record size exceeds file bounds at offset \{offset} in \{path}",
        )
      }

      // Extract record bytes
      let record_arr = Array::make(record_sz, (0).to_byte())
      for i = 0; i < record_sz; i = i + 1 {
        record_arr[i] = file_bytes[offset + i]
      }
      let record_bytes = Bytes::from_array(record_arr)
      let record = deserialize_record(record_bytes)

      records.push({ record, offset, size: record_sz })
      offset = offset + record_sz
    }

    records
  } catch {
    _ => raise MoonKVError::IOError("Failed to read records from file \{path}")
  }
}