diff --git a/include/object/xdrstream.h b/include/object/xdrstream.h
new file mode 100644
index 0000000000000000000000000000000000000000..717822ef6205666ff4463771b7e1dede4eed645f
--- /dev/null
+++ b/include/object/xdrstream.h
@@ -0,0 +1,42 @@
+#ifndef XDRSTREAM_H
+#define XDRSTREAM_H
+
+#include <stdint.h>
+
+class XDRStream {
+ private:
+	XDRStream(const XDRStream& copy);
+	uint32_t next_array_len;
+
+ public:
+	XDRStream() : next_array_len(0) {}
+	void setNextArrayLen(uint32_t len) {next_array_len = len;}
+
+	virtual void put(char c) = 0;
+
+	virtual void flush() {}
+
+	XDRStream & operator<<(char c);
+	XDRStream & operator<<(unsigned char c);
+	XDRStream & operator<<(unsigned short number);
+	XDRStream & operator<<(short number);
+	XDRStream & operator<<(unsigned int number);
+	XDRStream & operator<<(int number);
+	XDRStream & operator<<(unsigned long number);
+	XDRStream & operator<<(long number);
+	XDRStream & operator<<(unsigned long long number);
+	XDRStream & operator<<(long long number);
+	XDRStream & operator<<(const char *text);
+	XDRStream & operator<<(XDRStream & (*fun) (XDRStream &));
+};
+
+
+// FLUSH: flush XDRStream buffer
+XDRStream & flush(XDRStream & os);
+
+// TERM: zero-termination
+XDRStream & term(XDRStream & os);
+
+XDRStream & opaque(XDRStream & os);
+
+#endif //OUTPUTSTREAM_H
diff --git a/src/os/object/xdrstream.cc b/src/os/object/xdrstream.cc
new file mode 100644
index 0000000000000000000000000000000000000000..eb5ca87dca5d27e4fb90ad3d1d067f22bf549046
--- /dev/null
+++ b/src/os/object/xdrstream.cc
@@ -0,0 +1,106 @@
+#include "object/xdrstream.h"
+
+XDRStream & XDRStream::operator<<(unsigned char c)
+{
+	*this << (uint32_t)c;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(char c)
+{
+	*this << (int32_t)c;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(uint16_t number)
+{
+	*this << (uint32_t)number;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(int16_t number)
+{
+	*this << (int32_t)number;
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(uint32_t number)
+{
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(int32_t number)
+{
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(uint64_t number)
+{
+	put((number >> 56) & 0xffU);
+	put((number >> 48) & 0xffU);
+	put((number >> 40) & 0xffU);
+	put((number >> 32) & 0xffU);
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(int64_t number)
+{
+	put((number >> 56) & 0xffU);
+	put((number >> 48) & 0xffU);
+	put((number >> 40) & 0xffU);
+	put((number >> 32) & 0xffU);
+	put((number >> 24) & 0xffU);
+	put((number >> 16) & 0xffU);
+	put((number >> 8) & 0xffU);
+	put(number & 0xffU);
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(char const *data){
+	uint32_t i;
+	for (i = 0; i < next_array_len; i++) {
+		put(data[i]);
+	}
+	while ((i++) % 4 != 0){
+		put('\0');
+	}
+	return *this;
+}
+
+XDRStream & XDRStream::operator<<(XDRStream & (*fkt) (XDRStream &))
+{
+	return fkt(*this);
+}
+
+// FLUSH
+XDRStream & flush(XDRStream & os)
+{
+	os.flush();
+	return os;
+}
+
+// TERM: null-termination
+XDRStream & term(XDRStream & os)
+{
+	os.put('\0');
+	os.flush();
+	return os;
+}
+
+XDRStream & opaque(XDRStream & os)
+{
+	os.setNextArrayLen(3);
+	return os;
+}