class Aws::EventStream::Encoder

This class provides encode method for encoding Aws::EventStream::Message into binary.

## Examples

message = Aws::EventStream::Message.new(
  headers: {
    "foo" => Aws::EventStream::HeaderValue.new(
      value: "bar", type: "string"
     )
  },
  payload: "payload"
)
encoder = Aws::EventsStream::Encoder.new
file = Tempfile.new

# encode into IO ouput
encoder.encode(message, file)

# get encoded binary string
encoded_message = encoder.encode(message)

file.read == encoded_message
# => true

Constants

MAX_HEADERS_LENGTH

Maximum header length allowed (after encode) 128kb

MAX_PAYLOAD_LENGTH

Maximum payload length allowed (after encode) 16mb

OVERHEAD_LENGTH

bytes of total overhead in a message, including prelude and 4 bytes total message crc checksum

Public Instance Methods

encode(message, io = nil) click to toggle source

Encodes Aws::EventStream::Message to output IO when

provided, else return the encoded binary string

@param [Aws::EventStream::Message] message

@param [IO#write, nil] io An IO-like object that

responds to `#write`, encoded message will be
written to this IO when provided

@return [nil, String] when output IO is provided,

encoded message will be written to that IO, nil
will be returned. Else, encoded binary string is
returned.
# File lib/aws-eventstream/encoder.rb, line 63
def encode(message, io = nil)
  encoded = encode_message(message)
  if io
    io.write(encoded)
    io.close
  else
    encoded
  end
end
encode_headers(message) click to toggle source

Encodes headers part of an Aws::EventStream::Message

into String

@param [Aws::EventStream::Message] message

@return [String]

# File lib/aws-eventstream/encoder.rb, line 110
def encode_headers(message)
  header_entries = message.headers.map do |key, value|
    encoded_key = [key.bytesize, key].pack('Ca*')

    # header value
    pattern, value_length, type_index = Types.pattern[value.type]
    encoded_value = [type_index].pack('C')
    # boolean types doesn't need to specify value
    next [encoded_key, encoded_value].pack('a*a*') if !!pattern == pattern
    encoded_value = [encoded_value, value.value.bytesize].pack('a*S>') unless value_length

    [
      encoded_key,
      encoded_value,
      pattern ? [value.value].pack(pattern) : value.value,
    ].pack('a*a*a*')
  end
  header_entries.join.tap do |encoded_header|
    break encoded_header if encoded_header.bytesize <= MAX_HEADERS_LENGTH
    raise Aws::EventStream::Errors::EventHeadersLengthExceedError.new
  end
end
encode_message(message) click to toggle source

Encodes an Aws::EventStream::Message

into String

@param [Aws::EventStream::Message] message

@return [String]

# File lib/aws-eventstream/encoder.rb, line 79
def encode_message(message)
  # create context buffer with encode headers
  encoded_header = encode_headers(message)
  header_length = encoded_header.bytesize
  # encode payload
  if message.payload.length > MAX_PAYLOAD_LENGTH
    raise Aws::EventStream::Errors::EventPayloadLengthExceedError.new
  end
  encoded_payload = message.payload.read
  total_length = header_length + encoded_payload.bytesize + OVERHEAD_LENGTH

  # create message buffer with prelude section
  encoded_prelude = encode_prelude(total_length, header_length)

  # append message context (headers, payload)
  encoded_content = [
    encoded_prelude,
    encoded_header,
    encoded_payload,
  ].pack('a*a*a*')
  # append message checksum
  message_checksum = Zlib.crc32(encoded_content)
  [encoded_content, message_checksum].pack('a*N')
end

Private Instance Methods

encode_prelude(total_length, headers_length) click to toggle source
# File lib/aws-eventstream/encoder.rb, line 135
def encode_prelude(total_length, headers_length)
  prelude_body = [total_length, headers_length].pack('NN')
  checksum = Zlib.crc32(prelude_body)
  [prelude_body, checksum].pack('a*N')
end