class ByteArrayDataInput extends InputStream implements DataInput, VersionedDataStream {

  @Override
  public String readUTF() throws IOException {
    final int utfLen = readUnsignedShort();
    if (utfLen == 0) {
      return "";
    }

    if ((pos + utfLen) <= nBytes) {
      String asciiString = readASCII(utfLen);
      if (asciiString != null) {
        return asciiString;
      }
      if (charBuf == null || charBuf.length < utfLen) {
        int charBufLength = (((utfLen / 2) + 1) * 3);
        charBuf = new char[charBufLength];
      }
      final byte[] bytes = this.bytes;
      final char[] chars = charBuf;

      int index = pos;
      final int limit = index + utfLen;
      int nChars = 0;
      int char1, char2, char3;

      for (; index < limit; index++, nChars++) {
        char1 = (bytes[index] & 0xff);
        // classify based on the high order 3 bits
        switch (char1 >> 5) {
          case 6:
            if ((index + 1) < limit) {
              // two byte encoding
              // 110yyyyy 10xxxxxx
              // use low order 6 bits of the next byte
              // It should have high order bits 10.
              char2 = bytes[++index];
              if ((char2 & 0xc0) == 0x80) {
                // 00000yyy yyxxxxxx
                chars[nChars] = (char) ((char1 & 0x1f) << 6 | (char2 & 0x3f));
              } else {
                throwUTFEncodingError(index, char1, char2, null, 2);
              }
            } else {
              throw new UTFDataFormatException(
                  "partial 2-byte character at end (char1=" + char1 + ')');
            }
            break;
          case 7:
            if ((index + 2) < limit) {
              // three byte encoding
              // 1110zzzz 10yyyyyy 10xxxxxx
              // use low order 6 bits of the next byte
              // It should have high order bits 10.
              char2 = bytes[++index];
              if ((char2 & 0xc0) == 0x80) {
                // use low order 6 bits of the next byte
                // It should have high order bits 10.
                char3 = bytes[++index];
                if ((char3 & 0xc0) == 0x80) {
                  // zzzzyyyy yyxxxxxx
                  chars[nChars] =
                      (char) (((char1 & 0x0f) << 12) | ((char2 & 0x3f) << 6) | (char3 & 0x3f));
                } else {
                  throwUTFEncodingError(index, char1, char2, char3, 3);
                }
              } else {
                throwUTFEncodingError(index, char1, char2, null, 3);
              }
            } else {
              throw new UTFDataFormatException(
                  "partial 3-byte character at end (char1=" + char1 + ')');
            }
            break;
          default:
            // one byte encoding
            // 0xxxxxxx
            chars[nChars] = (char) char1;
            break;
        }
      }
      pos = limit;
      return new String(chars, 0, nChars);
    } else {
      throw new EOFException();
    }
  }

  public  ByteArrayDataInput();
  public  ByteArrayDataInput(byte[] bytes);
  public  ByteArrayDataInput(byte[] bytes, KnownVersion version);

}