Class: NNQ::CLI::Formatter

Inherits:
Object
  • Object
show all
Defined in:
lib/nnq/cli/formatter.rb

Overview

Handles encoding/decoding a single-body message in the configured format. Compression is handled by the NNQ::Zstd decorator around the socket, not by the formatter.

Unlike omq-cli’s Formatter, nnq messages are not multipart — one ‘String` body per message. The API still accepts/returns a 1-element array so that `$F`-based eval expressions work the same way.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format) ⇒ Formatter

Returns a new instance of Formatter.

Parameters:

  • format (Symbol)

    wire format (:ascii, :quoted, :raw, :jsonl, :msgpack, :marshal)



15
16
17
# File 'lib/nnq/cli/formatter.rb', line 15

def initialize(format)
  @format = format
end

Class Method Details

.preview(msg) ⇒ String

Formats a message body for human-readable preview (logging).

Parameters:

  • msg (Array<String>)

    single-element array

Returns:

  • (String)

    truncated preview



92
93
94
95
# File 'lib/nnq/cli/formatter.rb', line 92

def self.preview(msg)
  body = msg.first.to_s
  "(#{body.bytesize}B) #{preview_body(body)}"
end

.preview_body(body) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/nnq/cli/formatter.rb', line 98

def self.preview_body(body)
  bytes = body.b
  return "''" if bytes.empty?

  sample    = bytes[0, 12]
  printable = sample.count("\x20-\x7e")

  if printable < sample.bytesize / 2
    "[#{bytes.bytesize}B]"
  elsif bytes.bytesize > 12
    "#{sample.gsub(/[^[:print:]]/, ".")}..."
  else
    sample.gsub(/[^[:print:]]/, ".")
  end
end

Instance Method Details

#decode(line) ⇒ Array<String>

Decodes a formatted input line into a 1-element message array.

Parameters:

  • line (String)

    input line (newline-terminated)

Returns:

  • (Array<String>)

    1-element array



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/nnq/cli/formatter.rb', line 47

def decode(line)
  case @format
  when :ascii, :marshal
    [line.chomp]
  when :quoted
    ["\"#{line.chomp}\"".undump]
  when :raw
    [line]
  when :jsonl
    arr = JSON.parse(line.chomp)
    unless arr.is_a?(Array) && arr.all? { |e| e.is_a?(String) }
      abort "JSON Lines input must be an array of strings"
    end
    arr.first(1)
  end
end

#decode_marshal(io) ⇒ Object?

Decodes one Marshal object from the given IO stream.

Parameters:

  • io (IO)

    input stream

Returns:

  • (Object, nil)

    deserialized object, or nil on EOF



69
70
71
72
73
# File 'lib/nnq/cli/formatter.rb', line 69

def decode_marshal(io)
  Marshal.load(io)
rescue EOFError, TypeError
  nil
end

#decode_msgpack(io) ⇒ Object?

Decodes one MessagePack object from the given IO stream.

Parameters:

  • io (IO)

    input stream

Returns:

  • (Object, nil)

    deserialized object, or nil on EOF



80
81
82
83
84
85
# File 'lib/nnq/cli/formatter.rb', line 80

def decode_msgpack(io)
  @msgpack_unpacker ||= MessagePack::Unpacker.new(io)
  @msgpack_unpacker.read
rescue EOFError
  nil
end

#encode(msg) ⇒ String

Encodes a message body into a printable string for output.

Parameters:

  • msg (Array<String>)

    single-element array (the body)

Returns:

  • (String)

    formatted output line



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/nnq/cli/formatter.rb', line 24

def encode(msg)
  body = msg.first.to_s
  case @format
  when :ascii
    body.b.gsub(/[^[:print:]\t]/, ".") + "\n"
  when :quoted
    body.b.dump[1..-2] + "\n"
  when :raw
    body
  when :jsonl
    JSON.generate([body]) + "\n"
  when :msgpack
    MessagePack.pack([body])
  when :marshal
    body.inspect + "\n"
  end
end