docs: public State encode(HeaderMap headers, ByteBuffer target) {
          if(overflowData != null) {
              for(int i = overflowPos; i < overflowLength; ++i) {
                  if(!target.hasRemaining()) {
                      overflowPos = i;
                      return State.OVERFLOW;
                  }
                  target.put(overflowData[i]);
              }
              overflowData = null;
          }
  
          long it = headersIterator;
          if (headersIterator == -1) {
              handleTableSizeChange(target);
              //new headers map
              it = headers.fastIterate();
              currentHeaders = headers;
          } else {
              if (headers != currentHeaders) {
                  throw new IllegalStateException();
              }
          }
          while (it != -1) {
              HeaderValues values = headers.fiCurrent(it);
              boolean skip = false;
              if (firstPass) {
                  if (values.getHeaderName().byteAt(0) != ':') {
                      skip = true;
                  }
              } else {
                  if (values.getHeaderName().byteAt(0) == ':') {
                      skip = true;
                  }
              }
              if(SKIP.contains(values.getHeaderName())) {
                  //ignore connection specific headers
                  skip = true;
              }
              if (!skip) {
                  for (int i = 0; i < values.size(); ++i) {
  
                      HttpString headerName = values.getHeaderName();
                      int required = 11 + headerName.length(); //we use 11 to make sure we have enough room for the variable length itegers
  
                      String val = values.get(i);
                      for(int v = 0; v < val.length(); ++v) {
                          char c = val.charAt(v);
                          if(c == '\r' || c == '\n') {
                              val = val.replace('\r', ' ').replace('\n', ' ');
                              break;
                          }
                      }
                      TableEntry tableEntry = findInTable(headerName, val);
  
                      required += (1 + val.length());
                      boolean overflowing = false;
  
                      ByteBuffer current = target;
                      if (current.remaining() < required) {
                          overflowing = true;
                          current = ByteBuffer.wrap(overflowData = new byte[required]);
                          overflowPos = 0;
                      }
                      boolean canIndex = hpackHeaderFunction.shouldUseIndexing(headerName, val) && (headerName.length() + val.length() + 32) < maxTableSize; //only index if it will fit
                      if (tableEntry == null && canIndex) {
                          //add the entry to the dynamic table
                          current.put((byte) (1 << 6));
                          writeHuffmanEncodableName(current, headerName);
                          writeHuffmanEncodableValue(current, headerName, val);
                          addToDynamicTable(headerName, val);
                      } else if (tableEntry == null) {
                          //literal never indexed
                          current.put((byte) (1 << 4));
                          writeHuffmanEncodableName(current, headerName);
                          writeHuffmanEncodableValue(current, headerName, val);
                      } else {
                          //so we know something is already in the table
                          if (val.equals(tableEntry.value)) {
                              //the whole thing is in the table
                              current.put((byte) (1 << 7));
                              encodeInteger(current, tableEntry.getPosition(), 7);
                          } else {
                              if (canIndex) {
                                  //add the entry to the dynamic table
                                  current.put((byte) (1 << 6));
                                  encodeInteger(current, tableEntry.getPosition(), 6);
                                  writeHuffmanEncodableValue(current, headerName, val);
                                  addToDynamicTable(headerName, val);
  
                              } else {
                                  current.put((byte) (1 << 4));
                                  encodeInteger(current, tableEntry.getPosition(), 4);
                                  writeHuffmanEncodableValue(current, headerName, val);
                              }
                          }
                      }
                      if(overflowing) {
                          it = headers.fiNext(it);
                          this.headersIterator = it;
                          this.overflowLength = current.position();
                          return State.OVERFLOW;
                      }
  
                  }
              }
              it = headers.fiNext(it);
              if (it == -1 && firstPass) {
                  firstPass = false;
                  it = headers.fastIterate();
              }
          }
          headersIterator = -1;
          firstPass = true;
          return State.COMPLETE;
      }