docs: private void qrBinary(int[] datastream, int version, int target_binlen, QrMode[] inputMode, int[] inputData, boolean gs1, int eciMode, int est_binlen) {
  
          // TODO: make encodeInfo a StringBuilder, make this method static?
  
          int position = 0;
          int short_data_block_length, i;
          int padbits;
          int current_binlen, current_bytes;
          int toggle;
          QrMode data_block;
  
          StringBuilder binary = new StringBuilder(est_binlen + 12);
  
          if (gs1) {
              binary.append("0101"); /* FNC1 */
          }
  
          if (eciMode != 3) {
              binary.append("0111"); /* ECI (Table 4) */
              if (eciMode <= 127) {
                  binaryAppend(eciMode, 8, binary); /* 000000 to 000127 */
              } else if (eciMode <= 16383) {
                  binaryAppend(0x8000 + eciMode, 16, binary); /* 000000 to 016383 */
              } else {
                  binaryAppend(0xC00000 + eciMode, 24, binary); /* 000000 to 999999 */
              }
          }
  
          encodeInfo += "Encoding: ";
  
          do {
              data_block = inputMode[position];
              short_data_block_length = 0;
              do {
                  short_data_block_length++;
              } while (((short_data_block_length + position) < inputMode.length)
                      && (inputMode[position + short_data_block_length] == data_block));
  
              switch (data_block) {
  
                  case KANJI:
                      /* Kanji mode */
                      /* Mode indicator */
                      binary.append("1000");
  
                      /* Character count indicator */
                      binaryAppend(short_data_block_length, tribus(version, 8, 10, 12), binary);
  
                      encodeInfo += "KNJI ";
  
                      /* Character representation */
                      for (i = 0; i < short_data_block_length; i++) {
                          int jis = inputData[position + i];
                          if (jis >= 0x8140 && jis <= 0x9ffc) {
                              jis -= 0x8140;
                          } else if (jis >= 0xe040 && jis <= 0xebbf) {
                              jis -= 0xc140;
                          }
                          int prod = ((jis >> 8) * 0xc0) + (jis & 0xff);
                          binaryAppend(prod, 13, binary);
                          encodeInfo += Integer.toString(prod) + " ";
                      }
  
                      break;
  
                  case BINARY:
                      /* Byte mode */
                      /* Mode indicator */
                      binary.append("0100");
  
                      /* Character count indicator */
                      binaryAppend(short_data_block_length, tribus(version, 8, 16, 16), binary);
  
                      encodeInfo += "BYTE ";
  
                      /* Character representation */
                      for (i = 0; i < short_data_block_length; i++) {
                          int b = inputData[position + i];
                          if (b == FNC1) {
                              b = 0x1d; /* FNC1 */
                          }
                          binaryAppend(b, 8, binary);
                          encodeInfo += Integer.toString(b) + " ";
                      }
  
                      break;
  
                  case ALPHANUM:
                      /* Alphanumeric mode */
                      /* Mode indicator */
                      binary.append("0010");
  
                      /* If in GS1 mode, expand FNC1 -> '%' and expand '%' -> '%%' in a new array */
                      int percentCount = 0;
                      if (gs1) {
                          for (i = 0; i < short_data_block_length; i++) {
                              if (inputData[position + i] == '%') {
                                  percentCount++;
                              }
                          }
                      }
                      int[] inputExpanded = new int[short_data_block_length + percentCount];
                      percentCount = 0;
                      for (i = 0; i < short_data_block_length; i++) {
                          int c = inputData[position + i];
                          if (c == FNC1) {
                              inputExpanded[i + percentCount] = '%'; /* FNC1 */
                          } else {
                              inputExpanded[i + percentCount] = c;
                              if (gs1 && c == '%') {
                                  percentCount++;
                                  inputExpanded[i + percentCount] = c;
                              }
                          }
                      }
  
                      /* Character count indicator */
                      binaryAppend(inputExpanded.length, tribus(version, 9, 11, 13), binary);
  
                      encodeInfo += "ALPH ";
  
                      /* Character representation */
                      for (i = 0; i + 1 < inputExpanded.length; i += 2) {
                          int first = positionOf((char) inputExpanded[i], RHODIUM);
                          int second = positionOf((char) inputExpanded[i + 1], RHODIUM);
                          int prod = (first * 45) + second;
                          int count = 2;
                          binaryAppend(prod, 1 + (5 * count), binary);
                          encodeInfo += Integer.toString(prod) + " ";
                      }
                      if (inputExpanded.length % 2 != 0) {
                          int first = positionOf((char) inputExpanded[inputExpanded.length - 1], RHODIUM);
                          int prod = first;
                          int count = 1;
                          binaryAppend(prod, 1 + (5 * count), binary);
                          encodeInfo += Integer.toString(prod) + " ";
                      }
  
                      break;
  
                  case NUMERIC:
                      /* Numeric mode */
                      /* Mode indicator */
                      binary.append("0001");
  
                      /* Character count indicator */
                      binaryAppend(short_data_block_length, tribus(version, 10, 12, 14), binary);
  
                      encodeInfo += "NUMB ";
  
                      /* Character representation */
                      i = 0;
                      while (i < short_data_block_length) {
  
                          int first = Character.getNumericValue(inputData[position + i]);
                          int count = 1;
                          int prod = first;
  
                          if (i + 1 < short_data_block_length) {
                              int second = Character.getNumericValue(inputData[position + i + 1]);
                              count = 2;
                              prod = (prod * 10) + second;
  
                              if (i + 2 < short_data_block_length) {
                                  int third = Character.getNumericValue(inputData[position + i + 2]);
                                  count = 3;
                                  prod = (prod * 10) + third;
                              }
                          }
  
                          binaryAppend(prod, 1 + (3 * count), binary);
  
                          encodeInfo += Integer.toString(prod) + " ";
  
                          i += count;
                      };
  
                      break;
              }
  
              position += short_data_block_length;
  
          } while (position < inputMode.length);
  
          encodeInfo += "\n";
  
          /* Terminator */
          binary.append("0000");
  
          current_binlen = binary.length();
          padbits = 8 - (current_binlen % 8);
          if (padbits == 8) {
              padbits = 0;
          }
          current_bytes = (current_binlen + padbits) / 8;
  
          /* Padding bits */
          for (i = 0; i < padbits; i++) {
              binary.append('0');
          }
  
          /* Put data into 8-bit codewords */
          for (i = 0; i < current_bytes; i++) {
              datastream[i] = 0x00;
              for (int p = 0; p < 8; p++) {
                  if (binary.charAt((i * 8) + p) == '1') {
                      datastream[i] += (0x80 >> p);
                  }
              }
          }
  
          /* Add pad codewords */
          toggle = 0;
          for (i = current_bytes; i < target_binlen; i++) {
              if (toggle == 0) {
                  datastream[i] = 0xec;
                  toggle = 1;
              } else {
                  datastream[i] = 0x11;
                  toggle = 0;
              }
          }
  
          encodeInfo += "Codewords: ";
          for (i = 0; i < target_binlen; i++) {
              encodeInfo += Integer.toString(datastream[i]) + " ";
          }
          encodeInfo += "\n";
      }