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  //------------------------------------------------------------------------------