func (msg *Message) FreezeOriginal() {
	if msg.orig != nil {
		return
	}
	var metadata tcontainer.MarshalMap
	if msg.data.metadata != nil {
		metadata = msg.data.metadata.Clone()
	}
	msg.orig = &MessageData{
		payload:  getPayloadCopy(msg.data.payload),
		metadata: metadata,
	}
}
FreezeOriginal will take the current state of the message and store it as
the "original" message. This function can only be called once for each
message. Please note that this function only affects payload and metadata and
can only be called once. Additional calls will have no effect.
The original stream ID can be changed at any time by using SetOrigStreamID.
package core
import (
	"bytes"
	"encoding/gob"
	"time"
	"github.com/trivago/tgo/tcontainer"
	"github.com/golang/protobuf/proto"
)
type MessageData struct {
	payload  []byte
	metadata tcontainer.MarshalMap
}
type Message struct {
	data         MessageData
	orig         *MessageData
	streamID     MessageStreamID
	prevStreamID MessageStreamID
	origStreamID MessageStreamID
	source       MessageSource
	timestamp    int64
}
func NewMessage(source MessageSource, data []byte, metadata tcontainer.MarshalMap, streamID MessageStreamID) *Message {
	msg := &Message{
		source:       source,
		streamID:     streamID,
		origStreamID: streamID,
		timestamp:    time.Now().UnixNano(),
	}
	msg.data.payload = getPayloadCopy(data)
	if metadata != nil && len(metadata) > 0 {
		msg.data.metadata = metadata
	}
	return msg
}
func getPayloadCopy(data []byte) (buffer []byte) {
	buffer = make([]byte, len(data))
	copy(buffer, data)
	return
}
func (msg *Message) GetCreationTime() time.Time {
	return time.Unix(0, msg.timestamp)
}
func (msg *Message) GetStreamID() MessageStreamID {
	return msg.streamID
}
func (msg *Message) GetOrigStreamID() MessageStreamID {
	return msg.origStreamID
}
func (msg *Message) GetPrevStreamID() MessageStreamID {
	return msg.prevStreamID
}
func (msg *Message) GetRouter() Router {
	return StreamRegistry.GetRouterOrFallback(msg.GetStreamID())
}
func (msg *Message) GetPrevRouter() Router {
	return StreamRegistry.GetRouterOrFallback(msg.GetPrevStreamID())
}
func (msg *Message) GetOrigRouter() Router {
	return StreamRegistry.GetRouterOrFallback(msg.GetOrigStreamID())
}
func (msg *Message) SetStreamID(streamID MessageStreamID) {
	msg.prevStreamID = msg.streamID
	msg.streamID = streamID
}
func (msg *Message) SetlStreamIDAsOriginal(streamID MessageStreamID) {
	msg.SetStreamID(streamID)
	msg.origStreamID = streamID
}
func (msg *Message) GetSource() MessageSource {
	return msg.source
}
func (msg *Message) String() string {
	return string(msg.data.payload)
}
func (msg *Message) GetPayload() []byte {
	return msg.data.payload
}
func (msg *Message) GetMetadata() tcontainer.MarshalMap {
	if msg.data.metadata == nil {
		msg.data.metadata = NewMetadata()
	}
	return msg.data.metadata
}
func (msg *Message) TryGetMetadata() tcontainer.MarshalMap {
	return msg.data.metadata
}
func (msg *Message) StorePayload(data []byte) {
	if len(data) <= cap(msg.data.payload) {
		msg.data.payload = msg.data.payload[:len(data)]
		copy(msg.data.payload, data)
	} else {
		msg.data.payload = data
	}
}
func (msg *Message) Clone() *Message {
	clone := *msg
	clone.data.payload = make([]byte, len(msg.data.payload))
	copy(clone.data.payload, msg.data.payload)
	if clone.data.metadata != nil {
		clone.data.metadata = msg.data.metadata.Clone()
	}
	return &clone
}
func (msg *Message) CloneOriginal() *Message {
	if msg.orig == nil {
		msg.FreezeOriginal()
	}
	clone := *msg
	clone.data.payload = make([]byte, len(msg.orig.payload))
	copy(clone.data.payload, msg.orig.payload)
	if msg.orig.metadata != nil {
		clone.data.metadata = msg.orig.metadata.Clone()
	} else {
		clone.data.metadata = nil
	}
	clone.SetStreamID(msg.origStreamID)
	return &clone
}