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

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

Parameters:

  • buffer (String)

    mutable accumulation buffer

Yield Parameters:

  • msg (Hash)

    frozen: { type: :response|:event, headers:, raw:, action_id: }



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 = build_message(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