github.com/Jeffail/benthos/v3@v3.65.0/lib/message/message.go (about) 1 package message 2 3 import ( 4 "time" 5 6 "github.com/Jeffail/benthos/v3/lib/types" 7 ) 8 9 //------------------------------------------------------------------------------ 10 11 // Type is the standard implementation of types.Message, containing a multiple 12 // part message. 13 type Type struct { 14 createdAt time.Time 15 parts []types.Part 16 } 17 18 // New initializes a new message from a 2D byte slice, the slice can be nil. 19 func New(bslice [][]byte) *Type { 20 parts := make([]types.Part, len(bslice)) 21 for i, v := range bslice { 22 parts[i] = NewPart(v) 23 } 24 return &Type{ 25 createdAt: time.Now(), 26 parts: parts, 27 } 28 } 29 30 //------------------------------------------------------------------------------ 31 32 // Copy creates a new shallow copy of the message. Parts can be re-arranged in 33 // the new copy and JSON parts can be get/set without impacting other message 34 // copies. However, it is still unsafe to edit the raw content of message parts. 35 func (m *Type) Copy() types.Message { 36 parts := make([]types.Part, len(m.parts)) 37 for i, v := range m.parts { 38 parts[i] = v.Copy() 39 } 40 return &Type{ 41 createdAt: m.createdAt, 42 parts: parts, 43 } 44 } 45 46 // DeepCopy creates a new deep copy of the message. This can be considered an 47 // entirely new object that is safe to use anywhere. 48 func (m *Type) DeepCopy() types.Message { 49 parts := make([]types.Part, len(m.parts)) 50 for i, v := range m.parts { 51 parts[i] = v.DeepCopy() 52 } 53 return &Type{ 54 createdAt: m.createdAt, 55 parts: parts, 56 } 57 } 58 59 //------------------------------------------------------------------------------ 60 61 // Get returns a message part at a particular index, indexes can be negative. 62 func (m *Type) Get(index int) types.Part { 63 if index < 0 { 64 index = len(m.parts) + index 65 } 66 if index < 0 || index >= len(m.parts) { 67 return NewPart(nil) 68 } 69 if m.parts[index] == nil { 70 m.parts[index] = NewPart(nil) 71 } 72 return m.parts[index] 73 } 74 75 // SetAll changes the entire set of message parts. 76 func (m *Type) SetAll(parts []types.Part) { 77 m.parts = parts 78 } 79 80 // Append adds a new message part to the message. 81 func (m *Type) Append(b ...types.Part) int { 82 m.parts = append(m.parts, b...) 83 return len(m.parts) - 1 84 } 85 86 // Len returns the length of the message in parts. 87 func (m *Type) Len() int { 88 return len(m.parts) 89 } 90 91 // Iter will iterate all parts of the message, calling f for each. 92 func (m *Type) Iter(f func(i int, p types.Part) error) error { 93 for i, p := range m.parts { 94 if p == nil { 95 p = NewPart(nil) 96 m.parts[i] = p 97 } 98 if err := f(i, p); err != nil { 99 return err 100 } 101 } 102 return nil 103 } 104 105 // CreatedAt returns a timestamp whereby the message was created. 106 func (m *Type) CreatedAt() time.Time { 107 return m.createdAt 108 } 109 110 //------------------------------------------------------------------------------ 111 112 /* 113 Internal message blob format: 114 115 - Four bytes containing number of message parts in big endian 116 - For each message part: 117 + Four bytes containing length of message part in big endian 118 + Content of message part 119 120 # Of bytes in message part 2 121 | 122 # Of message parts (u32 big endian) | Content of message part 2 123 | | | 124 v v v 125 | 0| 0| 0| 2| 0| 0| 0| 5| h| e| l| l| o| 0| 0| 0| 5| w| o| r| l| d| 126 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 17 18 19 20 21 22 127 ^ ^ 128 | | 129 | Content of message part 1 130 | 131 # Of bytes in message part 1 (u32 big endian) 132 */ 133 134 // Reserve bytes for our length counter (4 * 8 = 32 bit) 135 var intLen uint32 = 4 136 137 // ToBytes serialises a message into a single byte array. 138 func ToBytes(m types.Message) []byte { 139 lenParts := uint32(m.Len()) 140 141 l := (lenParts + 1) * intLen 142 m.Iter(func(i int, p types.Part) error { 143 l += uint32(len(p.Get())) 144 return nil 145 }) 146 b := make([]byte, l) 147 148 b[0] = byte(lenParts >> 24) 149 b[1] = byte(lenParts >> 16) 150 b[2] = byte(lenParts >> 8) 151 b[3] = byte(lenParts) 152 153 b2 := b[intLen:] 154 155 m.Iter(func(i int, p types.Part) error { 156 le := uint32(len(p.Get())) 157 158 b2[0] = byte(le >> 24) 159 b2[1] = byte(le >> 16) 160 b2[2] = byte(le >> 8) 161 b2[3] = byte(le) 162 163 b2 = b2[intLen:] 164 165 copy(b2, p.Get()) 166 b2 = b2[len(p.Get()):] 167 return nil 168 }) 169 170 return b 171 } 172 173 // FromBytes deserialises a Message from a byte array. 174 func FromBytes(b []byte) (*Type, error) { 175 if len(b) < 4 { 176 return nil, ErrBadMessageBytes 177 } 178 179 numParts := uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) 180 if numParts >= uint32(len(b)) { 181 return nil, ErrBadMessageBytes 182 } 183 184 b = b[4:] 185 186 m := New(nil) 187 for i := uint32(0); i < numParts; i++ { 188 if len(b) < 4 { 189 return nil, ErrBadMessageBytes 190 } 191 partSize := uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) 192 b = b[4:] 193 194 if uint32(len(b)) < partSize { 195 return nil, ErrBadMessageBytes 196 } 197 m.Append(NewPart(b[:partSize])) 198 b = b[partSize:] 199 } 200 return m, nil 201 } 202 203 //------------------------------------------------------------------------------