/ src / msgpackiodevice.h
msgpackiodevice.h
  1  #ifndef NEOVIM_QT_MSGPACKIODEVICE
  2  #define NEOVIM_QT_MSGPACKIODEVICE
  3  
  4  #include <msgpack.h>
  5  #include <QHash>
  6  #include <QIODevice>
  7  #include <QVariant>
  8  
  9  namespace NeovimQt {
 10  
 11  class MsgpackRequest;
 12  class MsgpackRequestHandler;
 13  class MsgpackIODevice: public QObject
 14  {
 15  	Q_OBJECT
 16  	Q_PROPERTY(MsgpackError error READ errorCause NOTIFY error)
 17  public:
 18  	enum MsgpackError
 19  	{
 20  		NoError = 0,
 21  		InvalidDevice,
 22  		InvalidMsgpack,
 23  	};
 24  	Q_ENUM(MsgpackError)
 25  
 26  	MsgpackIODevice(QIODevice *, QObject *parent=0);
 27  	~MsgpackIODevice();
 28          static MsgpackIODevice* fromStdinOut(QObject *parent=0);
 29  
 30  	bool isOpen();
 31  	QString errorString() const;
 32  	MsgpackError errorCause() const {return m_error;};
 33  
 34  	QByteArray encoding() const;
 35  
 36  	quint32 msgId();
 37  	MsgpackRequest* startRequestUnchecked(const QString& method, quint32 argcount);
 38  
 39  	void send(int64_t);
 40  	void send(double);
 41  	void send(const QVariant&);
 42  	void send(const QByteArray&);
 43  	void send(bool);
 44  	void send(const QList<QByteArray>& list);
 45  	template <class T>
 46  	void sendArrayOf(const QList<T>& list) {
 47  		msgpack_pack_array(&m_pk, list.size());
 48  		foreach(const T& elem, list) {
 49  			send(elem);
 50  		}
 51  	}
 52  
 53  	// Convert string to the proper encoding to send to neovim (utf8)
 54  	inline QByteArray encode(const QString& str) { return str.toUtf8(); }
 55  	// Decode byte array as string, from Neovim's encoding
 56  	QString decode(const QByteArray& data) { return QString::fromUtf8(data); }
 57  	bool checkVariant(const QVariant&);
 58  
 59  	bool sendResponse(uint64_t msgid, const QVariant& err, const QVariant& res);
 60  	bool sendNotification(const QByteArray& method, const QVariantList& params);
 61  
 62  	void setRequestHandler(MsgpackRequestHandler *);
 63  
 64  	/** Typedef for msgpack-to-Qvariant decoder @see registerExtType */
 65  	typedef QVariant (*msgpackExtDecoder)(MsgpackIODevice*, const char* data, quint32 size);
 66  	void registerExtType(int8_t type, msgpackExtDecoder);
 67  
 68  	QList<quint32> pendingRequests() const;
 69  signals:
 70  	void error(NeovimQt::MsgpackIODevice::MsgpackError);
 71  	/** A notification with the given name and arguments was received */
 72  	void notification(const QByteArray &name, const QVariantList& args);
 73  	void encodingChanged(const QByteArray& encoding);
 74  	void aboutToClose();
 75  
 76  protected:
 77  	void sendError(const msgpack_object& req, const QString& msg);
 78  	void sendError(uint64_t msgid, const QString& msg);
 79  	void dispatch(msgpack_object& obj);
 80  	void dispatchRequest(msgpack_object& obj);
 81  	void dispatchResponse(msgpack_object& obj);
 82  	void dispatchNotification(msgpack_object& obj);
 83  
 84  	bool decodeMsgpack(const msgpack_object& in, int64_t& out);
 85  	bool decodeMsgpack(const msgpack_object& in, double& out);
 86  	bool decodeMsgpack(const msgpack_object& in, QVariant& out);
 87  	bool decodeMsgpack(const msgpack_object& in, QByteArray& out);
 88  	bool decodeMsgpack(const msgpack_object& in, bool& out);
 89  	bool decodeMsgpack(const msgpack_object& in, QList<QByteArray>& out);
 90  	bool decodeMsgpack(const msgpack_object& in, QList<int64_t>& out);
 91  	bool decodeMsgpack(const msgpack_object& in, QList<double>& out);
 92  	bool decodeMsgpack(const msgpack_object& in, QPoint& out);
 93  
 94  protected slots:
 95  	void setError(NeovimQt::MsgpackIODevice::MsgpackError err, const QString& msg);
 96  
 97  	void dataAvailable();
 98  	void dataAvailableStdin(const QByteArray&);
 99  	void dataAvailableFd(int fd);
100  
101  	void requestTimeout(quint32 id);
102  
103  private:
104  	static int msgpack_write_to_stdout(void* data, const char* buf, unsigned long int len);
105  	static int msgpack_write_to_dev(void* data, const char* buf, unsigned long int len);
106  
107  	quint32 m_reqid;
108  	QIODevice* m_dev;
109  	msgpack_packer m_pk;
110  	msgpack_unpacker m_uk;
111  	QHash<quint32, MsgpackRequest*> m_requests;
112  	MsgpackRequestHandler *m_reqHandler;
113  	QHash<int8_t, msgpackExtDecoder> m_extTypes;
114  
115  	QString m_errorString;
116  	MsgpackError m_error;
117  };
118  
119  class MsgpackRequestHandler {
120  public:
121  	virtual void handleRequest(MsgpackIODevice*, quint32 msgid, const QByteArray&, const QVariantList&)=0;
122  };
123  
124  } // Namespace NeovimQt
125  Q_DECLARE_METATYPE(NeovimQt::MsgpackIODevice::MsgpackError)
126  #endif