Module: RubyAsterisk::AMI::Parser
- Defined in:
- lib/ruby-asterisk/ami/parser.rb
Overview
Stateless module for parsing raw AMI byte streams into structured messages.
All methods are class-level and side-effect free; they can be called from any thread or Fiber without synchronization.
Constant Summary collapse
- DELIMITER =
"\r\n\r\n"- DELIMITER_LEN =
DELIMITER.length
Class Method Summary collapse
-
.build_message(raw) ⇒ Object
Builds a single frozen message hash from a raw AMI frame, or nil if the frame carries no recognised Response/Event header.
-
.drain(buffer) {|msg| ... } ⇒ Object
Extracts all complete AMI messages from
buffer(mutates it) and yields a frozen message hash for each one. -
.parse_headers(raw) ⇒ Object
Parses "Key: Value\r\n..." lines into a frozen hash.
Class Method Details
.build_message(raw) ⇒ Object
Builds a single frozen message hash from a raw AMI frame, or nil if the frame carries no recognised Response/Event header.
45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ruby-asterisk/ami/parser.rb', line 45 def self.(raw) headers = parse_headers(raw) return nil if headers.empty? frozen_raw = raw.freeze if headers.key?('Response') { type: :response, headers: headers, raw: frozen_raw, action_id: headers['ActionID'] }.freeze elsif headers.key?('Event') { type: :event, event: RubyAsterisk::AMI::Event.new(headers, frozen_raw) }.freeze end end |
.drain(buffer) {|msg| ... } ⇒ Object
Extracts all complete AMI messages from buffer (mutates it) and
yields a frozen message hash for each one.
35 36 37 38 39 40 41 |
# File 'lib/ruby-asterisk/ami/parser.rb', line 35 def self.drain(buffer) while (idx = buffer.index(DELIMITER)) raw = buffer.slice!(0, idx + DELIMITER_LEN) msg = (raw) yield msg if msg end end |
.parse_headers(raw) ⇒ Object
Parses "Key: Value\r\n..." lines into a frozen hash. Lines without a colon separator (e.g. the AMI welcome banner) are skipped.
17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/ruby-asterisk/ami/parser.rb', line 17 def self.parse_headers(raw) headers = {} raw.split(/\r?\n/).each do |line| next if line.empty? colon = line.index(':') next unless colon&.positive? headers[line[0, colon].freeze] = line[(colon + 1)..].strip.freeze end headers.freeze end |