Module: TNetstring
- Defined in:
- lib/tnetstring/version.rb,
lib/tnetstring.rb,
lib/tnetstring/errors.rb
Overview
:nodoc:
Defined Under Namespace
Modules: Version Classes: ProcessError
Class Method Summary collapse
-
.assert(truthy, message) ⇒ Object
:nodoc:.
-
.dump(obj) ⇒ Object
Constructs a tnetstring out of the given object.
-
.dump_dictionary(dict) ⇒ Object
:nodoc:.
-
.dump_list(list) ⇒ Object
:nodoc:.
-
.encode(obj) ⇒ Object
DEPRECATED: Please use
dump
instead. -
.parse(tnetstring) ⇒ Object
Converts a tnetstring into the encoded data structure.
-
.parse_boolean(data) ⇒ Object
:nodoc:.
-
.parse_dictionary(data) ⇒ Object
:nodoc:.
-
.parse_list(data) ⇒ Object
:nodoc:.
-
.parse_pair(data) ⇒ Object
:nodoc:.
-
.parse_payload(data) ⇒ Object
:nodoc:.
Class Method Details
.assert(truthy, message) ⇒ Object
:nodoc:
183 184 185 |
# File 'lib/tnetstring.rb', line 183 def self.assert(truthy, ) # :nodoc: raise ProcessError.new() unless truthy end |
.dump(obj) ⇒ Object
Constructs a tnetstring out of the given object. Valid Ruby object types include strings, integers, boolean values, nil, arrays, and hashes. Arrays and hashes may contain any of the previous valid Ruby object types, but hash keys must be strings.
Example
int = 12345
TNetstring.dump(int)
#=> '5:12345#'
hash = {'hello' => 'world'}
TNetstring.dump(hash)
#=> '16:5:hello,5:world,}'
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/tnetstring.rb', line 146 def self.dump(obj) if obj.kind_of?(Integer) int_str = obj.to_s "#{int_str.length}:#{int_str}#" elsif obj.kind_of?(Float) float_str = obj.to_s "#{float_str.length}:#{float_str}^" elsif obj.kind_of?(String) || obj.kind_of?(Symbol) "#{obj.length}:#{obj}," elsif obj.is_a?(TrueClass) "4:true!" elsif obj.is_a?(FalseClass) "5:false!" elsif obj == nil "0:~" elsif obj.kind_of?(Array) dump_list(obj) elsif obj.kind_of?(Hash) dump_dictionary(obj) else assert false, "Object must be of a primitive type: #{obj.inspect}" end end |
.dump_dictionary(dict) ⇒ Object
:nodoc:
175 176 177 178 179 180 181 |
# File 'lib/tnetstring.rb', line 175 def self.dump_dictionary(dict) # :nodoc: contents = dict.map do |key, value| assert key.kind_of?(String) || key.kind_of?(Symbol), "Dictionary keys must be Strings or Symbols" "#{dump(key)}#{dump(value)}" end.join "#{contents.length}:#{contents}}" end |
.dump_list(list) ⇒ Object
:nodoc:
170 171 172 173 |
# File 'lib/tnetstring.rb', line 170 def self.dump_list(list) # :nodoc: contents = list.map {|item| dump(item)}.join "#{contents.length}:#{contents}]" end |
.encode(obj) ⇒ Object
DEPRECATED: Please use dump
instead.
Constructs a tnetstring out of the given object. Valid Ruby object types include strings, integers, boolean values, nil, arrays, and hashes. Arrays and hashes may contain any of the previous valid Ruby object types, but hash keys must be strings.
Example
int = 12345
TNetstring.dump(int)
#=> '5:12345#'
hash = {'hello' => 'world'}
TNetstring.dump(hash)
#=> '16:5:hello,5:world,}'
124 125 126 127 |
# File 'lib/tnetstring.rb', line 124 def self.encode(obj) warn "[DEPRECATION] `encode` is deprecated. Please use `dump` instead." dump obj end |
.parse(tnetstring) ⇒ Object
Converts a tnetstring into the encoded data structure.
It expects a string argument prefixed with a valid tnetstring and returns a tuple of the parsed object and any remaining string input.
Example
str = '5:12345#'
TNetstring.parse(str)
#=> [12345, '']
str = '11:hello world,abc123'
#=> ['hello world', 'abc123']
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/tnetstring.rb', line 20 def self.parse(tnetstring) payload, payload_type, remain = parse_payload(tnetstring) value = case payload_type when '#' payload.to_i when '^' payload.to_f when ',' payload when ']' parse_list(payload) when '}' parse_dictionary(payload) when '~' assert payload.length == 0, "Payload must be 0 length for null" nil when '!' parse_boolean(payload) else assert false, "Invalid payload type: #{payload_type}" end [value, remain] end |
.parse_boolean(data) ⇒ Object
:nodoc:
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/tnetstring.rb', line 94 def self.parse_boolean(data) # :nodoc: case data when "false" false when "true" true else assert false, "Boolean wasn't 'true' or 'false'" end end |
.parse_dictionary(data) ⇒ Object
:nodoc:
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/tnetstring.rb', line 72 def self.parse_dictionary(data) # :nodoc: return {} if data.length == 0 key, value, extra = parse_pair(data) result = {key => value} while extra.length > 0 key, value, extra = parse_pair(extra) result[key] = value end result end |
.parse_list(data) ⇒ Object
:nodoc:
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/tnetstring.rb', line 59 def self.parse_list(data) # :nodoc: return [] if data.length == 0 list = [] value, remain = parse(data) list << value while remain.length > 0 value, remain = parse(remain) list << value end list end |
.parse_pair(data) ⇒ Object
:nodoc:
85 86 87 88 89 90 91 92 |
# File 'lib/tnetstring.rb', line 85 def self.parse_pair(data) # :nodoc: key, extra = parse(data) assert key.kind_of?(String) || key.kind_of?(Symbol), "Dictionary keys must be Strings or Symbols" assert extra, "Unbalanced dictionary store" value, extra = parse(extra) [key, value, extra] end |
.parse_payload(data) ⇒ Object
:nodoc:
44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/tnetstring.rb', line 44 def self.parse_payload(data) # :nodoc: assert data, "Invalid data to parse; it's empty" length, extra = data.split(':', 2) length = length.to_i assert length <= 999_999_999, "Data is longer than the specification allows" assert length >= 0, "Data length cannot be negative" payload, extra = extra[0, length], extra[length..-1] assert extra, "No payload type: #{payload}, #{extra}" payload_type, remain = extra[0,1], extra[1..-1] assert payload.length == length, "Data is wrong length: #{length} expected but was #{payload.length}" [payload, payload_type, remain] end |