private int[] readMetadata(ByteArrayInputStream inputStream, byte[] columnTypes)
     throws IOException {
   int[] metadata = new int[columnTypes.length];
   for (int i = 0; i < columnTypes.length; i++) {
     switch (ColumnType.byCode(columnTypes[i] & 0xFF)) {
       case FLOAT:
       case DOUBLE:
       case BLOB:
       case JSON:
       case GEOMETRY:
         metadata[i] = inputStream.readInteger(1);
         break;
       case BIT:
       case VARCHAR:
       case NEWDECIMAL:
         metadata[i] = inputStream.readInteger(2);
         break;
       case SET:
       case ENUM:
       case STRING:
         metadata[i] = bigEndianInteger(inputStream.read(2), 0, 2);
         break;
       case TIME_V2:
       case DATETIME_V2:
       case TIMESTAMP_V2:
         metadata[i] = inputStream.readInteger(1); // fsp (@see {@link ColumnType})
         break;
       default:
         metadata[i] = 0;
     }
   }
   return metadata;
 }
 private List<Serializable[]> deserializeRows(
     long tableId, BitSet includedColumns, ByteArrayInputStream inputStream) throws IOException {
   List<Serializable[]> result = new LinkedList<Serializable[]>();
   while (inputStream.available() > 0) {
     result.add(deserializeRow(tableId, includedColumns, inputStream));
   }
   return result;
 }
 @Override
 public TableMapEventData deserialize(ByteArrayInputStream inputStream) throws IOException {
   TableMapEventData eventData = new TableMapEventData();
   eventData.setTableId(inputStream.readLong(6));
   inputStream.skip(3); // 2 bytes reserved for future use + 1 for the length of database name
   eventData.setDatabase(inputStream.readZeroTerminatedString());
   inputStream.skip(1); // table name
   eventData.setTable(inputStream.readZeroTerminatedString());
   int numberOfColumns = inputStream.readPackedInteger();
   eventData.setColumnTypes(inputStream.read(numberOfColumns));
   inputStream.readPackedInteger(); // metadata length
   eventData.setColumnMetadata(readMetadata(inputStream, eventData.getColumnTypes()));
   eventData.setColumnNullability(inputStream.readBitSet(numberOfColumns, true));
   return eventData;
 }
 @Override
 public DeleteRowsEventData deserialize(ByteArrayInputStream inputStream) throws IOException {
   DeleteRowsEventData eventData = new DeleteRowsEventData();
   eventData.setTableId(inputStream.readLong(6));
   inputStream.readInteger(2); // reserved
   if (mayContainExtraInformation) {
     int extraInfoLength = inputStream.readInteger(2);
     inputStream.skip(extraInfoLength - 2);
   }
   int numberOfColumns = inputStream.readPackedInteger();
   eventData.setIncludedColumns(inputStream.readBitSet(numberOfColumns, true));
   eventData.setRows(
       deserializeRows(eventData.getTableId(), eventData.getIncludedColumns(), inputStream));
   return eventData;
 }