public static Packet<String> decodePacket(String data, boolean utf8decode) {
    int type;
    try {
      type = Character.getNumericValue(data.charAt(0));
    } catch (IndexOutOfBoundsException e) {
      type = -1;
    }

    if (utf8decode) {
      try {
        data = UTF8.decode(data);
      } catch (UTF8Exception e) {
        return err;
      }
    }

    if (type < 0 || type >= packetslist.size()) {
      return err;
    }

    if (data.length() > 1) {
      return new Packet<String>(packetslist.get(type), data.substring(1));
    } else {
      return new Packet<String>(packetslist.get(type));
    }
  }
  public static void encodePacket(Packet packet, boolean utf8encode, EncodeCallback callback) {
    if (packet.data instanceof byte[]) {
      @SuppressWarnings("unchecked")
      Packet<byte[]> _packet = packet;
      @SuppressWarnings("unchecked")
      EncodeCallback<byte[]> _callback = callback;
      encodeByteArray(_packet, _callback);
      return;
    }

    String encoded = String.valueOf(packets.get(packet.type));

    if (null != packet.data) {
      encoded +=
          utf8encode ? UTF8.encode(String.valueOf(packet.data)) : String.valueOf(packet.data);
    }

    @SuppressWarnings("unchecked")
    EncodeCallback<String> _callback = callback;
    _callback.call(encoded);
  }