package frame import ( "fmt" coder "git.hpds.cc/Component/mq_coder" "sync" ) var dataFramePool sync.Pool // DataFrame defines the data structure carried with user's data type DataFrame struct { metaFrame *MetaFrame payloadFrame *PayloadFrame } func (d *DataFrame) String() string { data := d.GetCarriage() length := len(data) if length > debugFrameSize { data = data[:debugFrameSize] } return fmt.Sprintf("tid=%s | tag=%#x | source=%s | data[%d]=%# x", d.metaFrame.tid, d.Tag(), d.SourceId(), length, data) } // NewDataFrame create `DataFrame` with a transactionId string, // consider change transactionID to UUID type later func NewDataFrame() *DataFrame { data := newDataFrame() data.metaFrame.tid = randString() return data } func newDataFrame() (data *DataFrame) { v := dataFramePool.Get() if v == nil { data = new(DataFrame) data.metaFrame = new(MetaFrame) data.payloadFrame = new(PayloadFrame) } else { data = v.(*DataFrame) } return } // Clean cleans DataFrame. // Note that: // 1/ if the client is calling WriteFrame(), it will automatically invoke Clean(), so there is no need to call Clean() separately. // 2/ The DataFrame will be unavailable after cleaned, do not access DataFrame after Clean() called. func (d *DataFrame) Clean() { // reset metadataFrame d.metaFrame.tid = "" d.metaFrame.metadata = d.metaFrame.metadata[:0] d.metaFrame.sourceId = "" d.metaFrame.broadcast = false // reset payloadFrame d.payloadFrame.Tag = Tag(0) d.payloadFrame.Carriage = d.payloadFrame.Carriage[:0] dataFramePool.Put(d) } // Type gets the type of Frame. func (d *DataFrame) Type() Type { return TagOfDataFrame } // Tag return the tag of carriage data. func (d *DataFrame) Tag() Tag { return d.payloadFrame.Tag } // SetCarriage set user's raw data in `DataFrame` func (d *DataFrame) SetCarriage(tag Tag, carriage []byte) { d.payloadFrame = &PayloadFrame{ Tag: tag, Carriage: carriage, } } // GetCarriage return user's raw data in `DataFrame` func (d *DataFrame) GetCarriage() []byte { return d.payloadFrame.Carriage } // TransactionId return transactionId string func (d *DataFrame) TransactionId() string { return d.metaFrame.TransactionId() } // SetTransactionId set transactionId string func (d *DataFrame) SetTransactionId(transactionId string) { d.metaFrame.SetTransactionId(transactionId) } // GetMetaFrame return MetaFrame. func (d *DataFrame) GetMetaFrame() *MetaFrame { return d.metaFrame } // GetDataTag return the Tag of user's data func (d *DataFrame) GetDataTag() Tag { return d.payloadFrame.Tag } // SetSourceId set the source id. func (d *DataFrame) SetSourceId(sourceId string) { d.metaFrame.SetSourceId(sourceId) } // SourceId returns source id func (d *DataFrame) SourceId() string { return d.metaFrame.SourceId() } // SetBroadcast set broadcast mode func (d *DataFrame) SetBroadcast(enabled bool) { d.metaFrame.SetBroadcast(enabled) } // IsBroadcast returns the broadcast mode is enabled func (d *DataFrame) IsBroadcast() bool { return d.metaFrame.IsBroadcast() } // Encode return coder encoded bytes of `DataFrame` func (d *DataFrame) Encode() []byte { data := coder.NewNodePacketEncoder(byte(d.Type())) // MetaFrame data.AddBytes(d.metaFrame.Encode()) // PayloadFrame data.AddBytes(d.payloadFrame.Encode()) return data.Encode() } // DecodeToDataFrame decode coder encoded bytes to `DataFrame` func DecodeToDataFrame(buf []byte) (*DataFrame, error) { packet := coder.NodePacket{} _, err := coder.DecodeToNodePacket(buf, &packet) if err != nil { return nil, err } data := new(DataFrame) data.metaFrame = new(MetaFrame) data.payloadFrame = new(PayloadFrame) if metaBlock, ok := packet.NodePackets[byte(TagOfMetaFrame)]; ok { err := DecodeToMetaFrame(metaBlock.GetRawBytes(), data.metaFrame) if err != nil { return nil, err } } if payloadBlock, ok := packet.NodePackets[byte(TagOfPayloadFrame)]; ok { err := DecodeToPayloadFrame(payloadBlock.GetRawBytes(), data.payloadFrame) if err != nil { return nil, err } } return data, nil }