Module: Protocol::MQTT::Property
- Defined in:
- lib/protocol/mqtt/property.rb
Overview
v5 property identifiers and property-block codec (§2.2.2).
A property block is: VBI-length-prefixed sequence of { identifier (VBI), value } pairs. Value type is fixed per identifier. All identifiers appear at most once per packet except 0x26 User Property, which may repeat.
Constant Summary collapse
- BYTE =
Value types
:byte- U16 =
:u16- U32 =
:u32- VBI_TYPE =
:vbi- UTF8 =
:utf8- BINARY =
:binary- STRING_PAIR =
:string_pair- TABLE =
Identifier → [symbolic_name, type]
{ 0x01 => [:payload_format_indicator, BYTE], 0x02 => [:message_expiry_interval, U32], 0x03 => [:content_type, UTF8], 0x08 => [:response_topic, UTF8], 0x09 => [:correlation_data, BINARY], 0x0B => [:subscription_identifier, VBI_TYPE], 0x11 => [:session_expiry_interval, U32], 0x12 => [:assigned_client_identifier, UTF8], 0x13 => [:server_keep_alive, U16], 0x15 => [:authentication_method, UTF8], 0x16 => [:authentication_data, BINARY], 0x17 => [:request_problem_information, BYTE], 0x18 => [:will_delay_interval, U32], 0x19 => [:request_response_information, BYTE], 0x1A => [:response_information, UTF8], 0x1C => [:server_reference, UTF8], 0x1F => [:reason_string, UTF8], 0x21 => [:receive_maximum, U16], 0x22 => [:topic_alias_maximum, U16], 0x23 => [:topic_alias, U16], 0x24 => [:maximum_qos, BYTE], 0x25 => [:retain_available, BYTE], 0x26 => [:user_property, STRING_PAIR], 0x27 => [:maximum_packet_size, U32], 0x28 => [:wildcard_subscription_available, BYTE], 0x29 => [:subscription_identifier_available, BYTE], 0x2A => [:shared_subscription_available, BYTE], }.freeze
- NAME_TO_ID =
TABLE.to_h { |id, (name, _t)| [name, id] }.freeze
- REPEATABLE =
Every identifier allows zero-or-one occurrence EXCEPT user_property (repeatable) and subscription_identifier (repeatable in PUBLISH only, for multiple matching subscriptions).
{ 0x26 => true, # user_property 0x0B => true, # subscription_identifier }.freeze
Class Method Summary collapse
-
.decode(reader) ⇒ Object
Decode a property block starting at the current position of a Codec::Reader.
-
.encode(properties) ⇒ Object
Encode a Hash of { name_symbol => value, user_property: [[k,v], …] } into a full property block (VBI length prefix + body).
Class Method Details
.decode(reader) ⇒ Object
Decode a property block starting at the current position of a Codec::Reader. Consumes VBI length + that many bytes. Returns a Hash keyed by name symbol. Unknown ids raise MalformedPacket.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/protocol/mqtt/property.rb', line 90 def self.decode(reader) length = reader.read_vbi raise MalformedPacket, "property block length exceeds remaining" if length > reader.remaining end_pos = reader.pos + length props = {} while reader.pos < end_pos id = reader.read_vbi entry = TABLE[id] or raise MalformedPacket, "unknown property id 0x#{id.to_s(16)}" name, type = entry value = decode_value(reader, type) if name == :user_property (props[:user_property] ||= []) << value elsif REPEATABLE[id] (props[name] ||= []) << value else raise MalformedPacket, "duplicate property #{name}" if props.key?(name) props[name] = value end end raise MalformedPacket, "property block overrun" if reader.pos != end_pos props end |
.encode(properties) ⇒ Object
Encode a Hash of { name_symbol => value, user_property: [[k,v], …] } into a full property block (VBI length prefix + body). Returns a frozen BINARY String.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/protocol/mqtt/property.rb', line 68 def self.encode(properties) body = Codec::Writer.new properties.each do |name, value| id = NAME_TO_ID[name] or raise ArgumentError, "unknown property: #{name}" _, type = TABLE[id] values = REPEATABLE[id] ? Array(value) : [value] values.each do |v| body.write_vbi(id) encode_value(body, type, v) end end out = Codec::Writer.new out.write_vbi(body.bytesize) out.write(body.bytes) out.bytes end |