#ifndef DATAMESSAGE_H_
#define DATAMESSAGE_H_

#define USE_MESSAGE_UTILITY

#include <memory>
#include <inttypes.h>

// use message utility
#ifdef USE_MESSAGE_UTILITY
  #include "ariba/utility/messages.h"
  namespace ariba {
    typedef utility::Message Message;
  }
#endif

namespace ariba {

// define sequence number type
typedef uint16_t seqnum_t;

/**
 * This class wraps different representations of a message. In its current
 * version is allows to specify binary data (as void*) with a size specifying
 * the number of bytes of data or an message object that can be
 * serialized if necessary. The main idea is, that simulation environments
 * do not necessarily need to serialize messages.
 *
 * For performance reasons methods of this class are inlined where possible!
 *
 * @author Sebastian Mies <mies@tm.uka.de>
 */
class DataMessage {
private:
	void* data;
	size_t size;
public:
	static const DataMessage UNSPECIFIED;

	inline DataMessage() {
		this->data = NULL;
		this->size = 0;
	}

	inline DataMessage( const void* data, const size_t size ) {
		this->data = const_cast<void*>(data);
		this->size = size;
	}

#ifdef USE_MESSAGE_UTILITY
	inline DataMessage( const Message* message ) {
		this->data = (void*)const_cast<Message*>(message);
		this->size = ~0;
	}

	inline DataMessage( const Message& message ) {
		this->data = (void*)const_cast<Message*>(&message);
		this->size = ~0;
	}

	inline Message* getMessage() const {
		return (Message*)data;
	}

	inline operator Message* () const {
		return (Message*)data;
	}
#endif

	inline bool isMessage() const {
		return size >= 0;
	}

	inline bool isData() const {
		return size == ~0;
	}

	inline void* getData() const {
		return data;
	}

	inline size_t getSize() const {
		return size;
	}

	inline bool isUnspecified() const {
		return data == NULL;
	}
};

} // namespace ariba

#endif /* DATAMESSAGE_H_ */
