bytemapper 1.0.13 → 1.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7915e2b8be3bcd3f677ed08c5a82e8fd135ab941ff9ab8b04c2148cfc7b8441
4
- data.tar.gz: c44bf0499a0d15dc77728770edf55a995a12b00987e76ea651eb249c09f0d2e7
3
+ metadata.gz: 9651d363a3ac3e436372c5527f7f8bed34015ea0687eaa93b3b89b31bd0bce81
4
+ data.tar.gz: 7ed18fc3bfd35527aea3eef93e038adc785019ae4857d00008639512d18bf974
5
5
  SHA512:
6
- metadata.gz: ea2aa731fde9ad3ef8f22a08d1b0abfa4de8803e7d7849af1ad1c0aebc9c865640e9e62f1ebc91293025c1b76b21cb5bd1b469d510005dead3a6723a6b4ef314
7
- data.tar.gz: 9cbb50a69eea518d210ac6fb7bcaeeb9a74ff8b0e6ad3a9ade5f68988d6839c7d2464e9c276781d45fac856704de011352463c60a3b03d563ff90fec16ccf488
6
+ metadata.gz: 6d1b379ef5e3322c9b010377702cc7d4c5d1043ebbb9038a56e723df6537c558e6c4ca9b8f0b812015de4dc1199cb7043ada03f00d3850292ef60e55949ab20f
7
+ data.tar.gz: 93db768253293483ff66349868b577704e75cce5f18169cd7b0eb3fc7e52906ebb1c0d0a28b944d260918bbc21987a59d84dfff1f3de08af7d30ff37be0b84a0
@@ -1,4 +1,4 @@
1
- # Bytemapper - Model arbitrary bytestrings as Ruby objects.
1
+ # Bytemapper - Model arbitrary bytestrings as Ruby objects.
2
2
  # Copyright (C) 2020 Jefferson Hudson
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify it under
@@ -16,54 +16,87 @@
16
16
 
17
17
  module Bytemapper
18
18
  require 'bytemapper/registry'
19
+ require 'bytemapper/shape'
20
+ require 'bytemapper/type'
19
21
  require 'bytemapper/nameable'
20
- require 'bytemapper/flattenable'
21
22
  require 'bytemapper/chunk'
22
23
 
23
24
  @@registry = Registry.new
24
25
 
25
- def self.wrap(obj, name = nil, wrapper = {})
26
- if (obj.is_a?(Array) || obj.is_a?(String) || obj.is_a?(Symbol))
27
- obj = registry.get(obj, name)
28
- raise ArgumentError.new "Failed to resolve symbol #{name}" if obj.nil?
29
- elsif obj.is_a?(Hash)
30
- obj.each do |k, v|
31
- wrapper[k] = wrap(v, k)
32
- wrapper.define_singleton_method(k) { self.send(:fetch, k) }
26
+ class << self
27
+
28
+ def register(obj, name, fqname = [])
29
+ return if obj.nil?
30
+ name = name.downcase.to_sym unless name.nil?
31
+ fqname << name unless name.nil?
32
+ if is_a_type?(obj)
33
+ name = fqname.size > 1 ? fqname.join('.') : fqname.first
34
+ obj = Type.new(obj)
35
+ put(obj, name)
36
+ elsif is_a_name?(obj)
37
+ register(get(obj), nil, fqname)
38
+ elsif is_a_shape?(obj)
39
+ if registered?(obj)
40
+ obj = get(obj)
41
+ put(obj, name)
42
+ else
43
+ shape = Shape.new
44
+ obj.each do |k,v|
45
+ shape[k] = register(v, k, [].concat(fqname))
46
+ end
47
+ put(shape, name)
48
+ end
49
+ else
50
+ put(obj, name)
33
51
  end
34
- wrapper.extend(Flattenable)
35
- obj = registry.put(wrapper, name)
36
- else
37
- raise ArgumentError.new "Invalid object"
38
52
  end
39
- obj
40
- end
53
+ alias :wrap :register
41
54
 
42
- def self.map(bytes, shape, name = nil)
43
- bytes.force_encoding(Encoding::ASCII_8BIT)
44
- bytes = StringIO.new(bytes)
45
- wrapper = self.wrap(shape, name)
46
- Chunk.new(bytes, wrapper, name)
47
- end
55
+ def is_a_type?(obj)
56
+ obj.is_a?(Type) ||
57
+ obj.is_a?(Array) &&
58
+ obj.size == 2 &&
59
+ obj.first.is_a?(Integer) &&
60
+ obj.last.is_a?(String)
61
+ end
48
62
 
49
- def self.registry
50
- @@registry
51
- end
63
+ def is_a_shape?(obj)
64
+ obj.is_a?(Hash)
65
+ end
66
+
67
+ def is_a_name?(obj)
68
+ obj.is_a?(String) || obj.is_a?(Symbol)
69
+ end
70
+
71
+ def map(bytes, shape, name = nil)
72
+ bytes.force_encoding(Encoding::ASCII_8BIT)
73
+ bytes = StringIO.new(bytes)
74
+ shape = wrap(shape, name)
75
+ Chunk.new(bytes, shape, name)
76
+ end
77
+
78
+ def registered?(obj)
79
+ registry.registered?(obj)
80
+ end
81
+
82
+ def get(obj)
83
+ registry.get(obj)
84
+ end
85
+
86
+ def put(obj, name)
87
+ registry.put(obj, name)
88
+ end
89
+
90
+ def print
91
+ registry.print
92
+ end
93
+
94
+ def registry
95
+ @@registry
96
+ end
52
97
 
53
- def reset(with_basic_types = true)
54
- [
55
- [:uint8_t, [8,'C']],
56
- [:bool, [8,'C']],
57
- [:uint16_t, [16,'S']],
58
- [:uint32_t, [32,'L']],
59
- [:uint64_t, [64,'Q']],
60
- [:int8_t, [8,'c']],
61
- [:int16_t, [16,'s']],
62
- [:int32_t, [32,'l']],
63
- [:int64_t, [64,'q']]
64
- ].each do |name, type|
65
- @@registry.put(type, name)
98
+ def reset(with_basic_types = true)
99
+ @@registry = Registry.new(with_basic_types)
66
100
  end
67
- @@registry
68
101
  end
69
102
  end
@@ -15,17 +15,25 @@
15
15
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
16
 
17
17
  module Bytemapper
18
- class Chunk
18
+ require 'bytemapper/flattenable'
19
+ class Chunk < Hash
20
+ include Flattenable
19
21
  attr_reader :bytes, :shape, :name
20
22
 
21
23
  def initialize(bytes, shape, name)
22
- @bytes = bytes
23
- @shape = shape
24
24
  @name = name
25
-
26
- shape.flatten.each do |k,v|
25
+ @shape = shape
26
+ @bytes = bytes.is_a?(StringIO) ? bytes : StringIO.new(bytes)
27
+ @bytes.truncate(shape.size)
28
+ replace(shape)
29
+ each_pair do |k,v|
30
+ self[k] = if v.is_a?(Hash)
31
+ Chunk.new(@bytes.read(v.size), v, k)
32
+ else
33
+ unpack(v)
34
+ end
27
35
  singleton_class.instance_eval { attr_reader k }
28
- instance_variable_set("@#{k.to_s}", unpack(v))
36
+ instance_variable_set("@#{k.to_s}", self[k])
29
37
  end
30
38
  end
31
39
 
@@ -42,7 +50,10 @@ module Bytemapper
42
50
  end
43
51
 
44
52
  def size
45
- @bytes.size
53
+ bytes.size
54
+ end
55
+
56
+ def print
46
57
  end
47
58
 
48
59
  def unpack(value, endian = nil)
@@ -1,18 +1,19 @@
1
- # Bytemapper - Model arbitrary bytestrings as Ruby objects.
1
+ # Bytemapper - Model arbitrary bytestrings as Ruby objects.
2
2
  # Copyright (C) 2020 Jefferson Hudson
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify it under
5
5
  # the terms of the GNU Affero General Public License as published by the Free
6
6
  # Software Foundation, either version 3 of the License, or (at your option) any
7
7
  # later version.
8
-
8
+ #
9
9
  # This program is distributed in the hope that it will be useful, but WITHOUT
10
10
  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
11
  # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
12
12
  # details.
13
-
13
+ #
14
14
  # You should have received a copy of the GNU Affero General Public License
15
15
  # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+
16
17
  module Bytemapper
17
18
  class Registry
18
19
  require 'bytemapper/nameable'
@@ -36,56 +37,62 @@ module Bytemapper
36
37
  end
37
38
 
38
39
  def registered?(obj)
39
- names.key?(obj) || objects.key?(obj.hash)
40
+ v = registered_name?(obj) if obj.respond_to?(:to_sym)
41
+ v || registered_obj?(obj)
40
42
  end
41
43
 
42
- def get(obj, name = nil)
43
- if (obj.is_a?(String) || obj.is_a?(Symbol))
44
- name = obj
45
- key = @names[obj]
46
- elsif (obj.is_a?(Array) || obj.is_a?(Hash))
47
- put(obj, name)
48
- key = obj.hash
44
+ def get(obj)
45
+ if registered_name?(obj)
46
+ obj = obj.to_sym.downcase
47
+ @objects.fetch(@names[obj]) unless obj.nil?
48
+ elsif registered_obj?(obj)
49
+ @objects.fetch(obj.hash)
49
50
  else
50
- raise ArgumentError "Invalid obj"
51
+ nil
51
52
  end
52
- @objects[key]
53
53
  end
54
54
 
55
55
  def put(obj, name = nil)
56
56
  obj = register_obj(obj)
57
- register_name(obj, name)
57
+ register_name(obj, name) unless name.nil?
58
58
  obj
59
59
  end
60
60
 
61
61
  def registered_name?(name)
62
- @names.key?(name)
62
+ if name.respond_to?(:to_sym)
63
+ name = name.to_sym.downcase
64
+ @names.key?(name)
65
+ else
66
+ false
67
+ end
63
68
  end
64
69
 
65
70
  def registered_obj?(obj)
66
- @objects.key?(obj.hash)
71
+ @objects.key?(obj.hash)
67
72
  end
68
73
 
69
74
  def register_obj(obj)
70
75
  unless registered_obj?(obj)
71
- obj.extend(Nameable)
72
- obj.names = Set.new
76
+ begin
77
+ obj.extend(Nameable)
78
+ obj.names = Set.new
79
+ rescue TypeError
80
+ end
73
81
  end
74
82
  @objects[obj.hash] ||= obj
75
83
  end
76
84
 
77
85
  def register_name(obj, name)
78
- unless name.nil?
79
- if registered_name?(name) && get(name) != obj
80
- raise ArgumentError.new 'Name is already registered'
81
- else
82
- name = name.to_sym
83
- @names[name] ||= obj.hash
84
- obj.names << name
85
- end
86
+ if registered_name?(name) && get(name) != obj
87
+ raise ArgumentError.new 'Name is already registered'
88
+ else
89
+ name = name.to_sym.downcase
90
+ @names[name] ||= obj.hash
91
+ obj.names << name if obj.respond_to?(:names)
86
92
  end
87
93
  obj
88
94
  end
95
+ alias :register_alias :register_name
89
96
 
90
97
  def print
91
98
  puts to_s
@@ -97,7 +104,7 @@ module Bytemapper
97
104
  # Buffer to build up output.
98
105
  buf = StringIO.new
99
106
 
100
- # Calculate the width of each column.
107
+ # Calculate the true max width of each column.
101
108
  widths = [
102
109
  @names.keys.size.zero? ? 0 : @names.keys.map(&:size).max + 1, # add space for the `:`
103
110
  7, # length of ID to print
@@ -105,6 +112,10 @@ module Bytemapper
105
112
  @objects.values.map { |v| v.to_s.size }.max
106
113
  ]
107
114
 
115
+ # Truncate more than `max_width` num chars
116
+ max_width = 60
117
+ widths = widths.map { |w| w > max_width ? max_width : w }
118
+
108
119
  # Add an extra space at the beginning and end of each column.
109
120
  widths = widths.map { |p| p += 2 }
110
121
 
@@ -125,21 +136,29 @@ module Bytemapper
125
136
 
126
137
  # Fixup the id string so it pads nicely
127
138
  idstr = id.positive? ? id.to_s[..5] : id.to_s[..6]
128
- idstr = id.positive? ? " #{idstr}" : " #{idstr}"
139
+ idstr = id.positive? ? " #{idstr}" : "#{idstr}"
129
140
 
130
- # Wrap each column value with whitespace.
141
+ # Generate the column values
131
142
  values = [
132
- name.empty? ? name : " :#{name} ",
133
- idstr,
134
- " #{obj.class.to_s} ",
135
- " #{obj.to_s} "
143
+ name.empty? ? name : ":#{name}",
144
+ idstr,
145
+ "#{obj.class.to_s}",
146
+ "#{obj.to_s}"
136
147
  ]
137
-
138
- # Calculate padding for each column.
139
- pads = widths.zip(values).map { |a,b| a - b.size }
148
+
149
+ # Pad the values to fit in their respective columns, truncating as
150
+ # needed to stay within `max_width`
151
+ values = widths.zip(values).map do |w,v|
152
+ q = w - v.size
153
+ if q < 2
154
+ " #{v[..w-7]} ... "
155
+ else
156
+ " #{v}#{" "*(q-1)}"
157
+ end
158
+ end
140
159
 
141
160
  values.size.times do |i|
142
- buf << "#{values[i]}#{' '*pads[i]}|"
161
+ buf << "#{values[i]}|"
143
162
  end
144
163
  buf << "\n"
145
164
  end
@@ -163,15 +182,20 @@ module Bytemapper
163
182
  def register_basic_types
164
183
  [
165
184
  [:uint8_t, [8,'C']],
185
+ [:uchar, [8,'C']],
166
186
  [:bool, [8,'C']],
167
187
  [:uint16_t, [16,'S']],
168
188
  [:uint32_t, [32,'L']],
169
189
  [:uint64_t, [64,'Q']],
170
190
  [:int8_t, [8,'c']],
191
+ [:char, [8,'c']],
171
192
  [:int16_t, [16,'s']],
172
193
  [:int32_t, [32,'l']],
173
194
  [:int64_t, [64,'q']]
174
- ].each { |name, type| put(type, name) }
195
+ ].each do |name, type|
196
+ type = Type.new(type)
197
+ put(type, name)
198
+ end
175
199
  end
176
200
  end
177
201
  end
@@ -0,0 +1,30 @@
1
+ # Bytemapper - Model arbitrary bytestrings as Ruby objects.
2
+ # Copyright (C) 2020 Jefferson Hudson
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it under
5
+ # the terms of the GNU Affero General Public License as published by the Free
6
+ # Software Foundation, either version 3 of the License, or (at your option) any
7
+ # later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
12
+ # details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ module Bytemapper
18
+ require 'bytemapper/flattenable'
19
+ require 'bytemapper/nameable'
20
+ class Shape < Hash
21
+ include Flattenable
22
+ include Nameable
23
+
24
+ def []=(k,v)
25
+ super
26
+ singleton_class.instance_eval { attr_reader k }
27
+ instance_variable_set("@#{k.to_s}", self[k])
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # Bytemapper - Model arbitrary bytestrings as Ruby objects.
2
+ # Copyright (C) 2020 Jefferson Hudson
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it under
5
+ # the terms of the GNU Affero General Public License as published by the Free
6
+ # Software Foundation, either version 3 of the License, or (at your option) any
7
+ # later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
12
+ # details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ module Bytemapper
18
+ require 'bytemapper/nameable'
19
+ class Type < Array
20
+ include Nameable
21
+
22
+ def size
23
+ first / 8
24
+ end
25
+ end
26
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bytemapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.13
4
+ version: 1.0.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jefferson Hudson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-26 00:00:00.000000000 Z
11
+ date: 2020-06-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Model and interact with bytestrings using Ruby objects.
14
14
  email: jefferson.hudson@gmail.com
@@ -21,6 +21,8 @@ files:
21
21
  - lib/bytemapper/flattenable.rb
22
22
  - lib/bytemapper/nameable.rb
23
23
  - lib/bytemapper/registry.rb
24
+ - lib/bytemapper/shape.rb
25
+ - lib/bytemapper/type.rb
24
26
  homepage: https://github.com/l4cr0ss/bytemapper
25
27
  licenses:
26
28
  - AGPL-3.0-or-later