csvEncodeAsync function

Future<void> csvEncodeAsync(
  1. Object items,
  2. StringSink sink
)

Implementation

Future<void> csvEncodeAsync(Object items, StringSink sink) async {
  Future<void> writeRow(dynamic item_) async {
    dynamic item = item_;
    if (item is Future) {
      item = await item;
    }
    if (item is! List) {
      try {
        item = (item as dynamic).toCsv();
        if (item is Future) {
          item = await item;
        }
      } on NoSuchMethodError {
        // ignore
      } catch (e) {
        rethrow;
      }
      if (item is! List) {
        throw Exception(
          'Expecting $item to be a List or have toCsv() function that returns List',
        );
      }
    }
    for (int i = 0; i < item.length; i++) {
      dynamic cell = item[i];
      if (cell is Future) {
        cell = await cell;
      }
      if (cell is! String) {
        cell = '$cell';
      }
      if (cell.isEmpty) {
        // do nothing
      } else {
        int index = 0;
        bool needsEscaping = cell[0] == '"';
        while (!needsEscaping && index < cell.length) {
          final current = cell[index++];
          needsEscaping = switch (current) {
            ',' => true,
            '\n' => true,
            _ => false,
          };
        }
        if (needsEscaping) {
          sink.write('"');
          for (int j = 0; j < cell.length; j++) {
            sink.write(switch (cell[j]) {
              '"' => '""',
              final symbol => symbol,
            });
          }
          sink.write('"');
        } else {
          sink.write(cell);
        }
      }
      if (i == item.length - 1) {
        sink.write('\r\n');
      } else {
        sink.write(',');
      }
    }
  }

  switch (items) {
    case Stream stream:
      await for (final item in stream) {
        await writeRow(item);
      }

    case Iterable iterable:
      for (final item in iterable) {
        await writeRow(item);
      }

    default:
      throw ArgumentError(
        'The "items" parameter must be an Iterable or a Stream.',
      );
  }
}