Class: Aws::EventStream::Encoder

Inherits:
Object
  • Object
show all
Defined in:
gems/aws-eventstream/lib/aws-eventstream/encoder.rb

Overview

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

  • #encode - encode Aws::EventStream::Message into binary when output IO-like object is provided, binary string would be written to IO. If not, the encoded binary string would be returned directly

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

Constant Summary collapse

OVERHEAD_LENGTH =

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

16
MAX_HEADER_NAME_LENGTH =

Maximum encoded length of a single header name (1-byte unsigned length field)

255
MAX_HEADER_VALUE_LENGTH =

Maximum encoded length of a string/bytes header value. The length field is two bytes (and could hold 65,535), but the protocol caps the value at the signed 16-bit maximum (INT16_MAX, 2**15 - 1), so the encoder must enforce the lower limit.

32_767
MAX_HEADERS_LENGTH =

Maximum header length allowed (after encode) 128kb

1024 * 128
MAX_PAYLOAD_LENGTH =

Maximum payload length allowed (after encode) 24mb

1024 * 1024 * 24

Instance Method Summary collapse

Instance Method Details

#encode(message, io = nil) ⇒ nil, String

Encodes Aws::EventStream::Message to output IO when provided, else return the encoded binary string

Parameters:

  • message (Aws::EventStream::Message)
  • io (IO#write, nil) (defaults to: nil) —

    An IO-like object that responds to #write, encoded message will be written to this IO when provided

Returns:

  • (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.



71
72
73
74
75
76
77
78
79
# File 'gems/aws-eventstream/lib/aws-eventstream/encoder.rb', line 71

def encode(message, io = nil)
  encoded = encode_message(message)
  if io
    io.write(encoded)
    io.close
  else
    encoded
  end
end

#encode_headers(message) ⇒ String

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

Parameters:

Returns:

  • (String)


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'gems/aws-eventstream/lib/aws-eventstream/encoder.rb', line 118

def encode_headers(message)
  header_entries = message.headers.map do |key, value|
    if key.bytesize > MAX_HEADER_NAME_LENGTH
      raise Aws::EventStream::Errors::EventHeaderNameLengthExceedError.new
    end
    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
    validate_fixed_width_value!(value, value_length) if value_length
    unless value_length
      # string and bytes types carry a 2-byte length prefix capped at INT16_MAX; reject
      # oversized values rather than letting bytesize wrap mod 65536.
      if value.value.bytesize > MAX_HEADER_VALUE_LENGTH
        raise Aws::EventStream::Errors::EventHeaderValueLengthExceedError.new
      end
      encoded_value = [encoded_value, value.value.bytesize].pack('a*S>')
    end

    [
      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) ⇒ String

Encodes an Aws::EventStream::Message into String

Parameters:

Returns:

  • (String)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'gems/aws-eventstream/lib/aws-eventstream/encoder.rb', line 87

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