decodeTabularArray function

List<Map<String, Object?>> decodeTabularArray(
  1. ArrayHeaderInfo header,
  2. LineCursor cursor,
  3. int baseDepth,
  4. ResolvedDecodeOptions options,
)

Decodes a tabular array

Implementation

List<Map<String, Object?>> decodeTabularArray(
  ArrayHeaderInfo header,
  LineCursor cursor,
  int baseDepth,
  ResolvedDecodeOptions options,
) {
  final objects = <Map<String, Object?>>[];
  final rowDepth = baseDepth + 1;

  // Track line range for blank line validation
  int? startLine;
  int? endLine;

  while (!cursor.atEnd() && objects.length < header.length) {
    final line = cursor.peek();
    if (line == null || line.depth < rowDepth) {
      break;
    }

    if (line.depth == rowDepth) {
      // Track first and last row line numbers
      startLine ??= line.lineNumber;
      endLine = line.lineNumber;

      cursor.advance();
      final values = parseDelimitedValues(line.content, header.delimiter);
      assertExpectedCount(
          values.length, header.fields!.length, 'tabular row values', options);

      final primitives = mapRowValuesToPrimitives(values);
      final obj = <String, Object?>{};

      for (int i = 0; i < header.fields!.length; i++) {
        obj[header.fields![i]] = primitives[i];
      }

      objects.add(obj);
    } else {
      break;
    }
  }

  assertExpectedCount(objects.length, header.length, 'tabular rows', options);

  // In strict mode, check for blank lines inside the array
  if (options.strict && startLine != null && endLine != null) {
    validateNoBlankLinesInRange(
      startLine, // From first row line
      endLine, // To last row line
      cursor.getBlankLines(),
      options.strict,
      'tabular array',
    );
  }

  // In strict mode, check for extra rows
  if (options.strict) {
    validateNoExtraTabularRows(cursor, rowDepth, header);
  }

  return objects;
}