func NewNack(from Msg, code int, e error) *Nack {
	nack := &Nack{
		Meta: NewMeta(NackMsg),
	}
	nack.Payload.For = from.UUID()
	nack.Payload.ForType = from.Type()
	nack.Payload.Code = code
	nack.Payload.Err = e
	nack.Payload.Message = e.Error()
	switch from := from.(type) {
	case *Call:
		nack.Payload.URI = from.Payload.URI
	case *Pub:
		nack.Payload.Channel = from.Payload.Channel
	case *Sub:
		nack.Payload.Channel = from.Payload.Channel
	case *Unsb:
		nack.Payload.Channel = from.Payload.Channel
	case *Ack:
		nack.Payload.For = from.Payload.For
		nack.Payload.ForType = from.Payload.ForType
		nack.Payload.URI = from.Payload.URI
		nack.Payload.Channel = from.Payload.Channel
	case *Nack:
		nack.Payload.For = from.Payload.For
		nack.Payload.ForType = from.Payload.ForType
		nack.Payload.URI = from.Payload.URI
		nack.Payload.Channel = from.Payload.Channel
	case *Evnt:
		nack.Payload.For = from.Payload.For
		nack.Payload.ForType = PubMsg
		nack.Payload.Channel = from.Payload.Channel
	case *Res:
		nack.Payload.For = from.Payload.For
		nack.Payload.ForType = CallMsg
		nack.Payload.URI = from.Payload.URI
	}
	return nack
}
NewNack creates a new Nack message to notify a failure to process
the from message.
package message
import (
	"encoding/json"
	"fmt"
	"io"
	"time"
	"github.com/pborman/uuid"
)
type Type int
const (
	startRead Type = iota
	CallMsg
	PubMsg
	SubMsg
	UnsbMsg
	endRead
	startWrite
	NackMsg
	AckMsg
	ResMsg
	EvntMsg
	endWrite
	customMsg Type = 256
)
var nextCustomMsg = customMsg
var lookupType = map[Type]string{
	CallMsg: "CALL",
	PubMsg:  "PUB",
	SubMsg:  "SUB",
	UnsbMsg: "UNSB",
	NackMsg: "NACK",
	AckMsg:  "ACK",
	ResMsg:  "RES",
	EvntMsg: "EVNT",
}
func Register(name string) Type {
	for _, v := range lookupType {
		if v == name {
			panic("Register called twice for " + name)
		}
	}
	mt := nextCustomMsg
	nextCustomMsg++
	lookupType[mt] = name
	return mt
}
func (mt Type) String() string {
	if s := lookupType[mt]; s != "" {
		return lookupType[mt]
	}
	return fmt.Sprintf("<unknown: %d>", mt)
}
func (mt Type) IsRead() bool {
	return startRead < mt && mt < endRead
}
func (mt Type) IsWrite() bool {
	return startWrite < mt && mt < endWrite
}
func (mt Type) IsStd() bool {
	return mt.IsRead() || mt.IsWrite()
}
type Msg interface {
	Type() Type
	UUID() uuid.UUID
}
type Meta struct {
	T Type      `json:"type"`
	U uuid.UUID `json:"uuid"`
}
func NewMeta(t Type) Meta {
	return Meta{T: t, U: uuid.NewRandom()}
}
type partialMsg struct {
	Meta    Meta            `json:"meta"`
	Payload json.RawMessage `json:"payload"`
}
func (m Meta) Type() Type {
	return m.T
}
func (m Meta) UUID() uuid.UUID {
	return m.U
}
type Call struct {
	Meta    `json:"meta"`
	Payload struct {
		URI     string          `json:"uri"`
		Timeout time.Duration   `json:"timeout"`
		Args    json.RawMessage `json:"args"`
	} `json:"payload"`
}
func NewCall(uri string, args interface{}, timeout time.Duration) (*Call, error) {
	b, err := json.Marshal(args)
	if err != nil {
		return nil, err
	}
	c := &Call{
		Meta: NewMeta(CallMsg),
	}
	c.Payload.URI = uri
	c.Payload.Timeout = timeout
	c.Payload.Args = json.RawMessage(b)
	return c, nil
}
type Sub struct {
	Meta    `json:"meta"`
	Payload struct {
		Channel string `json:"channel"`
		Pattern bool   `json:"pattern"`
	} `json:"payload"`
}
func NewSub(channel string, pattern bool) *Sub {
	sub := &Sub{
		Meta: NewMeta(SubMsg),
	}
	sub.Payload.Channel = channel
	sub.Payload.Pattern = pattern
	return sub
}
type Unsb Sub
func NewUnsb(channel string, pattern bool) *Unsb {
	un := &Unsb{
		Meta: NewMeta(UnsbMsg),
	}
	un.Payload.Channel = channel
	un.Payload.Pattern = pattern
	return un
}
type Pub struct {
	Meta    `json:"meta"`
	Payload struct {
		Channel string          `json:"channel"`
		Args    json.RawMessage `json:"args"`
	} `json:"payload"`
}
func NewPub(channel string, args interface{}) (*Pub, error) {
	b, err := json.Marshal(args)
	if err != nil {
		return nil, err
	}
	p := &Pub{
		Meta: NewMeta(PubMsg),
	}
	p.Payload.Channel = channel
	p.Payload.Args = json.RawMessage(b)
	return p, nil
}
type Nack struct {
	Meta    `json:"meta"`
	Payload struct {
		For     uuid.UUID `json:"for"`
		ForType Type      `json:"for_type"`
		URI     string    `json:"uri,omitempty"`      
		Channel string    `json:"channel,omitempty"`  
		Code    int       `json:"code"`
		Message string    `json:"message"`  
		Err     error     `json:"-"`        
	} `json:"payload"`
}