amq-protocol 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d6619ef67f8b1e30048f898796d21854eae2a35dfdfe83286e0a5e894cbbf1c
4
- data.tar.gz: 0d62824daba6da208b96b7681e4c1db4f5c32a93a7a8a7714b875b8ad8f603e2
3
+ metadata.gz: e3f43ce885cd75341d0b5b784857aada66eab3990174d7b145b572a04286f41f
4
+ data.tar.gz: 7ec8798e7d34ec8d4218b209e67d75fc45fe254e80997d761f8c7c2cf0521366
5
5
  SHA512:
6
- metadata.gz: cac00e1594a26adcb0863b6505ba789e8fce9a1dee3a38584e58cf838479661ba857a37ac3d747c69e7751549e15877a6478dd51559a8003af70c68e856badb1
7
- data.tar.gz: 040e923fd9dcf5931a157007835085ec30b7ac44897c5a76ee05545f14f76cf431a3611f73fddb562e6bf9230fb82151fc808bfed24bc2244f12c85164541b6e
6
+ metadata.gz: 378697156e2adf582c060b1be25c374f68cf7764008cebf926a07a3c1f02f7669680e2d934a4cec94a18f3e779889a45b4998113a076844d4298e230914683c6
7
+ data.tar.gz: 8ff53d0b35d42dbfa6a515391b26593340446ceb985740bd1ec6d5e0cb043beef4d46e7c262ee918ac753a4a96db746e1dceaba4fc8b479228340045080650ee
data/AGENTS.md ADDED
@@ -0,0 +1,23 @@
1
+ # Instructions for AI Agents
2
+
3
+ ## Overview
4
+
5
+ This is a pure Ruby implementation of a AMQP 0-9-1 protocol parser
6
+ (more specifically% serialization, deserialization, framing) used by
7
+ [Bunny](https://github.com/ruby-amqp/bunny), a Ruby AMQP 0-9-1 client for RabbitMQ.
8
+
9
+ ## Target Ruby Version
10
+
11
+ This library targets Ruby 3.0 and later versions.
12
+
13
+ ## Comments
14
+
15
+ * Only add very important comments, both in tests and in the implementation
16
+
17
+ ## Git Instructions
18
+
19
+ * Never add yourself to the list of commit co-authors
20
+
21
+ ## Style Guide
22
+
23
+ * Never add full stops to Markdown list items
data/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ AGENTS.md
data/ChangeLog.md CHANGED
@@ -1,12 +1,16 @@
1
- ## Changes between 2.4.0 and 2.5.0 (in development)
1
+ ## Changes between 2.5.0 and 2.6.0 (in development)
2
2
 
3
3
  No changes yet.
4
4
 
5
- ## Changes between 2.3.4 and 2.4.0 (Dec 30, 2025)
6
5
 
7
- ### Bug Fixes
6
+ ## Changes between 2.4.0 and 2.5.0 (Dec 31, 2025)
7
+
8
+ ### Additional Consumer Hot Path Optimizations
9
+
10
+ A few more decode method optimizations for consumer delivery code paths.
8
11
 
9
- * Fixed `BadResponseError` constructor which referenced undefined variable `data` instead of `actual`
12
+
13
+ ## Changes between 2.3.4 and 2.4.0 (Dec 30, 2025)
10
14
 
11
15
  ### Performance Improvements
12
16
 
data/GEMINI.md ADDED
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -1569,30 +1569,31 @@ module AMQ
1569
1569
  0x0004,
1570
1570
  ]
1571
1571
 
1572
+ # Optimized decode_properties using getbyte and unpack1
1572
1573
  def self.decode_properties(data)
1573
1574
  offset, data_length, properties = 0, data.bytesize, {}
1574
1575
 
1575
- compressed_index = data[offset, 2].unpack(PACK_UINT16)[0]
1576
+ compressed_index = data.byteslice(offset, 2).unpack1(PACK_UINT16)
1576
1577
  offset += 2
1577
1578
  while data_length > offset
1578
1579
  DECODE_PROPERTIES_KEYS.each do |key|
1579
1580
  next unless compressed_index >= key
1580
1581
  compressed_index -= key
1581
- name = DECODE_PROPERTIES[key] || raise(RuntimeError.new("No property found for index #{index.inspect}!"))
1582
+ name = DECODE_PROPERTIES[key] || raise(RuntimeError.new("No property found for index #{key.inspect}!"))
1582
1583
  case DECODE_PROPERTIES_TYPE[key]
1583
1584
  when :shortstr
1584
- size = data[offset, 1].unpack(PACK_CHAR)[0]
1585
+ size = data.getbyte(offset)
1585
1586
  offset += 1
1586
- result = data[offset, size]
1587
+ result = data.byteslice(offset, size)
1587
1588
  when :octet
1588
1589
  size = 1
1589
- result = data[offset, size].unpack(PACK_CHAR).first
1590
+ result = data.getbyte(offset)
1590
1591
  when :timestamp
1591
1592
  size = 8
1592
- result = Time.at(data[offset, size].unpack(PACK_UINT64_BE).last)
1593
+ result = Time.at(data.byteslice(offset, 8).unpack1(PACK_UINT64_BE))
1593
1594
  when :table
1594
- size = 4 + data[offset, 4].unpack(PACK_UINT32)[0]
1595
- result = Table.decode(data[offset, size])
1595
+ size = 4 + data.byteslice(offset, 4).unpack1(PACK_UINT32)
1596
+ result = Table.decode(data.byteslice(offset, size))
1596
1597
  end
1597
1598
  properties[name] = result
1598
1599
  offset += size
@@ -1688,13 +1689,11 @@ module AMQ
1688
1689
  @index = 0x003C0015 # 60, 21, 3932181
1689
1690
  @packed_indexes = [60, 21].pack(PACK_UINT16_X2).freeze
1690
1691
 
1692
+ # Optimized decode using getbyte
1691
1693
  # @return
1692
1694
  def self.decode(data)
1693
- offset = offset = 0 # self-assigning offset to eliminate "assigned but unused variable" warning even if offset is not used in this method
1694
- length = data[offset, 1].unpack(PACK_CHAR).first
1695
- offset += 1
1696
- consumer_tag = data[offset, length]
1697
- offset += length
1695
+ length = data.getbyte(0)
1696
+ consumer_tag = data.byteslice(1, length)
1698
1697
  self.new(consumer_tag)
1699
1698
  end
1700
1699
 
@@ -1866,26 +1865,25 @@ module AMQ
1866
1865
  @index = 0x003C003C # 60, 60, 3932220
1867
1866
  @packed_indexes = [60, 60].pack(PACK_UINT16_X2).freeze
1868
1867
 
1868
+ # Optimized decode using getbyte and unpack1 for better performance
1869
1869
  # @return
1870
1870
  def self.decode(data)
1871
- offset = offset = 0 # self-assigning offset to eliminate "assigned but unused variable" warning even if offset is not used in this method
1872
- length = data[offset, 1].unpack(PACK_CHAR).first
1871
+ offset = 0
1872
+ length = data.getbyte(offset)
1873
1873
  offset += 1
1874
- consumer_tag = data[offset, length]
1874
+ consumer_tag = data.byteslice(offset, length)
1875
1875
  offset += length
1876
- delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
1876
+ delivery_tag = data.byteslice(offset, 8).unpack1(PACK_UINT64_BE)
1877
1877
  offset += 8
1878
- bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
1878
+ redelivered = (data.getbyte(offset) & 1) != 0
1879
1879
  offset += 1
1880
- redelivered = (bit_buffer & (1 << 0)) != 0
1881
- length = data[offset, 1].unpack(PACK_CHAR).first
1880
+ length = data.getbyte(offset)
1882
1881
  offset += 1
1883
- exchange = data[offset, length]
1882
+ exchange = data.byteslice(offset, length)
1884
1883
  offset += length
1885
- length = data[offset, 1].unpack(PACK_CHAR).first
1884
+ length = data.getbyte(offset)
1886
1885
  offset += 1
1887
- routing_key = data[offset, length]
1888
- offset += length
1886
+ routing_key = data.byteslice(offset, length)
1889
1887
  self.new(consumer_tag, delivery_tag, redelivered, exchange, routing_key)
1890
1888
  end
1891
1889
 
@@ -2009,14 +2007,11 @@ module AMQ
2009
2007
  @index = 0x003C0050 # 60, 80, 3932240
2010
2008
  @packed_indexes = [60, 80].pack(PACK_UINT16_X2).freeze
2011
2009
 
2010
+ # Optimized decode using unpack1 and getbyte
2012
2011
  # @return
2013
2012
  def self.decode(data)
2014
- offset = offset = 0 # self-assigning offset to eliminate "assigned but unused variable" warning even if offset is not used in this method
2015
- delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
2016
- offset += 8
2017
- bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
2018
- offset += 1
2019
- multiple = (bit_buffer & (1 << 0)) != 0
2013
+ delivery_tag = data.byteslice(0, 8).unpack1(PACK_UINT64_BE)
2014
+ multiple = (data.getbyte(8) & 1) != 0
2020
2015
  self.new(delivery_tag, multiple)
2021
2016
  end
2022
2017
 
@@ -2141,15 +2136,13 @@ module AMQ
2141
2136
  @index = 0x003C0078 # 60, 120, 3932280
2142
2137
  @packed_indexes = [60, 120].pack(PACK_UINT16_X2).freeze
2143
2138
 
2139
+ # Optimized decode using unpack1 and getbyte
2144
2140
  # @return
2145
2141
  def self.decode(data)
2146
- offset = offset = 0 # self-assigning offset to eliminate "assigned but unused variable" warning even if offset is not used in this method
2147
- delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
2148
- offset += 8
2149
- bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
2150
- offset += 1
2151
- multiple = (bit_buffer & (1 << 0)) != 0
2152
- requeue = (bit_buffer & (1 << 1)) != 0
2142
+ delivery_tag = data.byteslice(0, 8).unpack1(PACK_UINT64_BE)
2143
+ bit_buffer = data.getbyte(8)
2144
+ multiple = (bit_buffer & 1) != 0
2145
+ requeue = (bit_buffer & 2) != 0
2153
2146
  self.new(delivery_tag, multiple, requeue)
2154
2147
  end
2155
2148
 
@@ -60,9 +60,11 @@ This functionality is part of the https://github.com/ruby-amqp/amq-client librar
60
60
  EOF
61
61
  end
62
62
 
63
+ # Optimized header decode using unpack1 for single values where appropriate
63
64
  def self.decode_header(header)
64
65
  raise EmptyResponseError if header == nil || header.empty?
65
66
 
67
+ # Use unpack for multiple values - this is the optimal approach
66
68
  type_id, channel, size = header.unpack(PACK_CHAR_UINT16_UINT32)
67
69
  type = TYPES_REVERSE[type_id]
68
70
  raise FrameTypeError.new(TYPES_OPTIONS) unless type
@@ -1,5 +1,5 @@
1
1
  module AMQ
2
2
  module Protocol
3
- VERSION = "2.4.0"
3
+ VERSION = "2.5.0"
4
4
  end # Protocol
5
5
  end # AMQ
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amq-protocol
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Stastny
@@ -28,7 +28,10 @@ files:
28
28
  - ".gitmodules"
29
29
  - ".rspec"
30
30
  - ".travis.yml"
31
+ - AGENTS.md
32
+ - CLAUDE.md
31
33
  - ChangeLog.md
34
+ - GEMINI.md
32
35
  - Gemfile
33
36
  - LICENSE
34
37
  - README.md