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:
178 179 180 |
# File 'lib/tnetstring.rb', line 178 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,}'
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/tnetstring.rb', line 144 def self.dump(obj) if obj.kind_of?(Integer) int_str = obj.to_s "#{int_str.length}:#{int_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:
170 171 172 173 174 175 176 |
# File 'lib/tnetstring.rb', line 170 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:
165 166 167 168 |
# File 'lib/tnetstring.rb', line 165 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,}'
122 123 124 125 |
# File 'lib/tnetstring.rb', line 122 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 |
# 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 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:
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/tnetstring.rb', line 92 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:
70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/tnetstring.rb', line 70 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:
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/tnetstring.rb', line 57 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:
83 84 85 86 87 88 89 90 |
# File 'lib/tnetstring.rb', line 83 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:
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/tnetstring.rb', line 42 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 |