convert method

String convert(
  1. Iterable iterable,
  2. {List<int> expected}
)
override

Converts input and returns the result of the conversion.

Implementation

String convert(Iterable iterable, {List<int> expected}) {
  if (iterable.isEmpty && expected == null) {
    return "(no bytes)";
  }
  final sb = new StringBuffer();

  // Print "\n" so the first actual line will be aligned with the second one.
  sb.write("\n");

  final list = iterable.toList();
  var maxLength = list.length;
  if (expected != null && expected.length > maxLength) {
    maxLength = expected.length;
  }

  void maybePrintDifferenceLine(int start, int end) {
    if (expected == null) {
      return;
    }
    var equal = true;
    for (var i = start; i < end; i++) {
      if (i >= list.length ||
          i >= expected.length ||
          list[i] != expected[i]) {
        equal = false;
        break;
      }
    }
    const prefix = "        ";
    sb.write("(${start})".padLeft(prefix.length - 1, " "));
    if (equal) {
      // Print empty line
      sb.write("\n");
      // Print empty line
      sb.write("\n");
      return;
    }
    sb.write(" ");

    // Print markings
    var printExpectedBytes = false;
    int firstAt;
    final lineSb = new StringBuffer();
    for (var i = start; i < end; i++) {
      lineSb.write(getSpaceBefore(i));
      if (i >= list.length) {
        lineSb.write("^^"); // "Should be inserted"
        printExpectedBytes = true;
        firstAt ??= i;
      } else if (i >= expected.length) {
        lineSb.write("--"); // "Should be deleted"
        firstAt ??= i;
      } else if (list[i] != expected[i]) {
        lineSb.write("^^"); // "Should be changed"
        printExpectedBytes = true;
        firstAt ??= i;
      } else {
        lineSb.write("  "); // "OK"
      }
    }
    if (firstAt != null && firstAt > start) {
      lineSb.write("  <-- index of the first error: 0x");
      lineSb.write(firstAt.toRadixString(16).toUpperCase());
      lineSb.write(" (decimal: $firstAt)");
    }
    sb.write(lineSb.toString().trimRight());
    sb.write("\n");

    if (printExpectedBytes) {
      final lineSb = new StringBuffer();
      // Print another line for expected bytes
      lineSb.write(prefix);
      for (var i = start; i < end; i++) {
        lineSb.write(getSpaceBefore(i));
        if (i < expected.length &&
            (i >= list.length || list[i] != expected[i])) {
          // "Should be this byte"
          lineSb.write(expected[i].toRadixString(16).padLeft(2, "0"));
        } else {
          // "OK"
          lineSb.write("  ");
        }
      }
      sb.write(lineSb.toString().trimRight());
      sb.write("\n");
      // Print empty line
      sb.write("\n");
    } else {
      // Print empty line
      sb.write("\n");
    }
  }

  var rowStart = 0;
  for (var i = 0; i < maxLength; i++) {
    if (i % bytesPerRow == 0) {
      // Beginning of a row
      if (i > 0) {
        // Not the first row
        sb.write("\n");
        if (i > 0) {
          maybePrintDifferenceLine(
            rowStart,
            i,
          );
          rowStart = i;
        }
      }
      sb.write("0x");
      sb.write(i.toRadixString(16).padLeft(4, "0").toUpperCase());
      sb.write(": ");
    }
    sb.write(getSpaceBefore(i));
    if (i >= list.length) {
      sb.write(" ");
      continue;
    }
    final item = list[i];
    if (item is int) {
      sb.write(item.toRadixString(16).padLeft(2, "0"));
    } else {
      sb.write("{ ");
      sb.write(item);
      sb.write(" }");
    }
  }
  sb.write("\n");
  maybePrintDifferenceLine(
    rowStart,
    maxLength,
  );
  return sb.toString();
}