github.com/cyverse/go-irodsclient@v0.13.2/irods/message/message.go (about) 1 package message 2 3 import ( 4 "bytes" 5 "encoding/xml" 6 7 "golang.org/x/xerrors" 8 ) 9 10 // MessageType is a message type 11 type MessageType string 12 13 // IRODSMessageHeader defines a message header 14 type IRODSMessageHeader struct { 15 XMLName xml.Name `xml:"MsgHeader_PI"` 16 Type MessageType `xml:"type"` 17 MessageLen uint32 `xml:"msgLen"` 18 ErrorLen uint32 `xml:"errorLen"` 19 BsLen uint32 `xml:"bsLen"` 20 IntInfo int32 `xml:"intInfo"` 21 } 22 23 // IRODSMessageBody defines a message body 24 type IRODSMessageBody struct { 25 Type MessageType 26 Message []byte 27 Error []byte 28 Bs []byte 29 IntInfo int32 30 } 31 32 // IRODSMessage defines a message 33 type IRODSMessage struct { 34 Header *IRODSMessageHeader 35 Body *IRODSMessageBody 36 } 37 38 // IRODSMessageSerializationInterface is an interface for serializaing/deserializing of message 39 type IRODSMessageSerializationInterface interface { 40 GetBytes() ([]byte, error) 41 FromBytes(bodyBytes []byte, bsBytes []byte) error 42 } 43 44 // MakeIRODSMessageHeader makes a message header 45 func MakeIRODSMessageHeader(messageType MessageType, messageLen uint32, errorLen uint32, bsLen uint32, intInfo int32) *IRODSMessageHeader { 46 return &IRODSMessageHeader{ 47 Type: messageType, 48 MessageLen: messageLen, 49 ErrorLen: errorLen, 50 BsLen: bsLen, 51 IntInfo: intInfo, 52 } 53 } 54 55 // GetBytes returns byte array 56 func (header *IRODSMessageHeader) GetBytes() ([]byte, error) { 57 xmlBytes, err := xml.Marshal(header) 58 if err != nil { 59 return nil, xerrors.Errorf("failed to marshal irods message to xml: %w", err) 60 } 61 return xmlBytes, nil 62 } 63 64 // FromBytes returns struct from bytes 65 func (header *IRODSMessageHeader) FromBytes(bytes []byte) error { 66 err := xml.Unmarshal(bytes, header) 67 if err != nil { 68 return xerrors.Errorf("failed to unmarshal xml to irods message: %w", err) 69 } 70 return nil 71 } 72 73 // GetBytes returns byte array 74 func (body *IRODSMessageBody) GetBytes() ([]byte, error) { 75 messageBuffer := &bytes.Buffer{} 76 if body.Message != nil { 77 _, err := messageBuffer.Write(body.Message) 78 if err != nil { 79 return nil, xerrors.Errorf("failed to write to message buffer: %w", err) 80 } 81 } 82 83 if body.Error != nil { 84 _, err := messageBuffer.Write(body.Error) 85 if err != nil { 86 return nil, xerrors.Errorf("failed to write to message buffer: %w", err) 87 } 88 } 89 90 if body.Bs != nil { 91 _, err := messageBuffer.Write(body.Bs) 92 if err != nil { 93 return nil, xerrors.Errorf("failed to write to message buffer: %w", err) 94 } 95 } 96 97 return messageBuffer.Bytes(), nil 98 } 99 100 // GetBytesWithoutBS returns byte array of body without BS 101 func (body *IRODSMessageBody) GetBytesWithoutBS() ([]byte, error) { 102 messageBuffer := new(bytes.Buffer) 103 if body.Message != nil { 104 _, err := messageBuffer.Write(body.Message) 105 if err != nil { 106 return nil, xerrors.Errorf("failed to write to message buffer: %w", err) 107 } 108 } 109 110 if body.Error != nil { 111 _, err := messageBuffer.Write(body.Error) 112 if err != nil { 113 return nil, xerrors.Errorf("failed to write to message buffer: %w", err) 114 } 115 } 116 117 return messageBuffer.Bytes(), nil 118 } 119 120 // FromBytes returns struct from bytes 121 func (body *IRODSMessageBody) FromBytes(header *IRODSMessageHeader, bodyBytes []byte, bsBytes []byte) error { 122 if len(bodyBytes) < (int(header.MessageLen) + int(header.ErrorLen)) { 123 return xerrors.Errorf("bodyBytes given is too short to be parsed") 124 } 125 126 if len(bsBytes) < int(header.BsLen) { 127 return xerrors.Errorf("bsBytes given is too short to be parsed") 128 } 129 130 offset := 0 131 body.Message = bodyBytes[offset : offset+int(header.MessageLen)] 132 133 offset += int(header.MessageLen) 134 body.Error = bodyBytes[offset : offset+int(header.ErrorLen)] 135 136 offset += int(header.ErrorLen) 137 body.Bs = bsBytes[:int(header.BsLen)] 138 139 return nil 140 } 141 142 // BuildHeader returns IRODSMessageHeader 143 func (body *IRODSMessageBody) BuildHeader() (*IRODSMessageHeader, error) { 144 messageLen := 0 145 errorLen := 0 146 bsLen := 0 147 148 if body.Message != nil { 149 messageLen = len(body.Message) 150 } 151 152 if body.Error != nil { 153 errorLen = len(body.Error) 154 } 155 156 if body.Bs != nil { 157 bsLen = len(body.Bs) 158 } 159 160 h := MakeIRODSMessageHeader(body.Type, uint32(messageLen), uint32(errorLen), uint32(bsLen), body.IntInfo) 161 return h, nil 162 }