docs: final String readString(int position, Charset encoding) {
          // Sanity check the string size int position. Note that the eventual
          // m_buffer.get() does check for underflow, getInt() does not.
          if (STRING_LEN_SIZE > m_buffer.limit() - position) {
              throw new RuntimeException(String.format(
                      "VoltTableRow::readString: Can't read string size as %d byte integer " +
                      "from buffer with %d bytes remaining.",
                      STRING_LEN_SIZE, m_buffer.limit() - position));
          }
          final int len = m_buffer.getInt(position);
          //System.out.println(len);
  
          // check for null string
          if (len == VoltTable.NULL_STRING_INDICATOR)
              return null;
  
          if (len < 0) {
              throw new RuntimeException("Invalid object length.");
          }
  
          // Sanity check the size against the remaining buffer size.
          if (position + STRING_LEN_SIZE + len > m_buffer.limit()) {
              throw new RuntimeException(String.format(
                      "VoltTableRow::readString: Can't read %d byte string " +
                      "from buffer with %d bytes remaining.",
                      len, m_buffer.limit() - position - STRING_LEN_SIZE));
          }
  
          // this is a bit slower than directly getting the array (see below)
          // but that caused bugs
          byte[] stringData = new byte[len];
          int oldPos = m_buffer.position();
          m_buffer.position(position + STRING_LEN_SIZE);
          m_buffer.get(stringData);
          m_buffer.position(oldPos);
  
          return new String(stringData, encoding);
      }