tnetstring 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/tnetstring.rb CHANGED
@@ -1,4 +1,22 @@
1
+ require 'tnetstring/errors'
2
+
1
3
  module TNetstring
4
+ # Converts a tnetstring into the encoded data structure.
5
+ #
6
+ # It expects a string argument prefixed with a valid tnetstring and
7
+ # returns a tuple of the parsed object and any remaining string input.
8
+ #
9
+ # === Example
10
+ #
11
+ # str = '5:12345#'
12
+ # TNetstring.parse(str)
13
+ #
14
+ # #=> [12345, '']
15
+ #
16
+ # str = '11:hello world,abc123'
17
+ #
18
+ # #=> ['hello world', 'abc123']
19
+ #
2
20
  def self.parse(tnetstring)
3
21
  payload, payload_type, remain = parse_payload(tnetstring)
4
22
  value = case payload_type
@@ -11,7 +29,7 @@ module TNetstring
11
29
  when '}'
12
30
  parse_dictionary(payload)
13
31
  when '~'
14
- assert payload.length == 0, "Payload must be 0 length for null."
32
+ assert payload.length == 0, "Payload must be 0 length for null"
15
33
  nil
16
34
  when '!'
17
35
  parse_boolean(payload)
@@ -21,22 +39,22 @@ module TNetstring
21
39
  [value, remain]
22
40
  end
23
41
 
24
- def self.parse_payload(data)
25
- assert data, "Invalid data to parse, it's empty."
42
+ def self.parse_payload(data) # :nodoc:
43
+ assert data, "Invalid data to parse; it's empty"
26
44
  length, extra = data.split(':', 2)
27
45
  length = length.to_i
28
46
  assert length <= 999_999_999, "Data is longer than the specification allows"
29
- assert length >= 0, "Data length cannot be negative!"
47
+ assert length >= 0, "Data length cannot be negative"
30
48
 
31
49
  payload, extra = extra[0, length], extra[length..-1]
32
- assert extra, "No payload type: %s, %s" % [payload, extra]
50
+ assert extra, "No payload type: #{payload}, #{extra}"
33
51
  payload_type, remain = extra[0,1], extra[1..-1]
34
52
 
35
- assert payload.length == length, "Data is wrong length %d vs %d" % [length, payload.length]
53
+ assert payload.length == length, "Data is wrong length: #{length} expected but was #{payload.length}"
36
54
  [payload, payload_type, remain]
37
55
  end
38
56
 
39
- def self.parse_list(data)
57
+ def self.parse_list(data) # :nodoc:
40
58
  return [] if data.length == 0
41
59
  list = []
42
60
  value, remain = parse(data)
@@ -49,7 +67,7 @@ module TNetstring
49
67
  list
50
68
  end
51
69
 
52
- def self.parse_dictionary(data)
70
+ def self.parse_dictionary(data) # :nodoc:
53
71
  return {} if data.length == 0
54
72
 
55
73
  key, value, extra = parse_pair(data)
@@ -62,26 +80,44 @@ module TNetstring
62
80
  result
63
81
  end
64
82
 
65
- def self.parse_pair(data)
83
+ def self.parse_pair(data) # :nodoc:
66
84
  key, extra = parse(data)
67
- assert extra, "Unbalanced dictionary store."
85
+ assert key.kind_of?(String), "Dictionary keys must be Strings"
86
+ assert extra, "Unbalanced dictionary store"
68
87
  value, extra = parse(extra)
69
- assert value, "Got an invalid value, null not allowed."
88
+ assert value, "Got an invalid value, null not allowed"
70
89
 
71
90
  [key, value, extra]
72
91
  end
73
92
 
74
- def self.parse_boolean(data)
93
+ def self.parse_boolean(data) # :nodoc:
75
94
  case data
76
95
  when "false"
77
96
  false
78
97
  when "true"
79
98
  true
80
99
  else
81
- raise "Boolean wasn't 'true' or 'false'"
100
+ assert false, "Boolean wasn't 'true' or 'false'"
82
101
  end
83
102
  end
84
103
 
104
+ # Constructs a tnetstring out of the given object. Valid Ruby object types
105
+ # include strings, integers, boolean values, nil, arrays, and hashes. Arrays
106
+ # and hashes may contain any of the previous valid Ruby object types, but
107
+ # hash keys must be strings.
108
+ #
109
+ # === Example
110
+ #
111
+ # int = 12345
112
+ # TNetstring.encode(int)
113
+ #
114
+ # #=> '5:12345#'
115
+ #
116
+ # hash = {'hello' => 'world'}
117
+ # TNetstring.encode(hash)
118
+ #
119
+ # #=> '16:5:hello,5:world,}'
120
+ #
85
121
  def self.encode(obj)
86
122
  if obj.kind_of?(Integer)
87
123
  int_str = obj.to_s
@@ -98,16 +134,16 @@ module TNetstring
98
134
  elsif obj.kind_of?(Hash)
99
135
  encode_dictionary(obj)
100
136
  else
101
- assert false, "Object must be of a primitive type"
137
+ assert false, "Object must be of a primitive type: #{obj.inspect}"
102
138
  end
103
139
  end
104
140
 
105
- def self.encode_list(list)
141
+ def self.encode_list(list) # :nodoc:
106
142
  contents = list.map {|item| encode(item)}.join
107
143
  "#{contents.length}:#{contents}]"
108
144
  end
109
145
 
110
- def self.encode_dictionary(dict)
146
+ def self.encode_dictionary(dict) # :nodoc:
111
147
  contents = dict.map do |key, value|
112
148
  assert key.kind_of?(String), "Dictionary keys must be Strings"
113
149
  "#{encode(key)}#{encode(value)}"
@@ -115,7 +151,7 @@ module TNetstring
115
151
  "#{contents.length}:#{contents}}"
116
152
  end
117
153
 
118
- def self.assert(truthy, message)
119
- raise message unless truthy
154
+ def self.assert(truthy, message) # :nodoc:
155
+ raise ProcessError.new(message) unless truthy
120
156
  end
121
157
  end
@@ -0,0 +1,3 @@
1
+ module TNetstring
2
+ class ProcessError < StandardError; end
3
+ end
@@ -1,5 +1,5 @@
1
1
  module TNetstring # :nodoc:
2
2
  module Version # :nodoc:
3
- STRING = '0.3.0'
3
+ STRING = '0.3.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 0
9
- version: 0.3.0
8
+ - 1
9
+ version: 0.3.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Matt Yoho
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-04-16 00:00:00 -04:00
17
+ date: 2011-04-17 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -56,6 +56,7 @@ extensions: []
56
56
  extra_rdoc_files: []
57
57
 
58
58
  files:
59
+ - lib/tnetstring/errors.rb
59
60
  - lib/tnetstring/version.rb
60
61
  - lib/tnetstring.rb
61
62
  has_rdoc: true