bytemapper 1.0.16 → 1.0.22

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: 58da2db82a64cfd1b6eebdb6f61e238a018a9d7722cc28e1a26f0ee9992a8191
4
- data.tar.gz: 597ac65da785151a480b7ea756e990d5420e1df8ce7218f6fcb80e1f32f5b5d8
3
+ metadata.gz: 9383a019c471ccf2979e92c7c2e8a8c7a20f5c63fa74613837c2d38a84632a52
4
+ data.tar.gz: 903ecf62d057d5ee4f478e022df4129cccf1c9ce545ab60eeef1314bbcbaad67
5
5
  SHA512:
6
- metadata.gz: 40178210ff809c91e5f4661b7d24f79d565ee1fc7d47d1c3694dcf1db1ff330687c849831ffa495db7111748993e1dcef2e7877787c696b3102eeb3c6d84e7d1
7
- data.tar.gz: 8c42f01a701f7bb2a842764efa76f27fef54be61edfff32f100c606851eaecbcea41ab0a10e84b898cffc6efaf30effdaa5c4f4414f166c7a8f4ae3ee3637ec7
6
+ metadata.gz: 753673f95b723b32f1c0b1aa9dc88418e9e1bc740bc07185a4f5896c05fb388be68f23b5192aeba58bfb3d1c90368687cfda1d7d51471527b1e16e9b0d1b102e
7
+ data.tar.gz: 21e687cb299ee9aee44a068df8c37cc7a5cca987b7c7175d3677eb3af9ae26a74e5ddc10c1ce8eada691502202a8b5d36dc65e19972e3ac8b70e3e47d2f223c3
@@ -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,97 @@
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 "Object must not be nil" 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
+ if shape.is_a?(Array)
75
+ chunks = []
76
+ shape.each { |s| chunks << Chunk.new(bytes.read(s.size), s, name) }
77
+ chunks
78
+ else
79
+ shape = wrap(shape, name)
80
+ Chunk.new(bytes, shape, name)
81
+ end
82
+ end
83
+
84
+ def registered?(obj)
85
+ registry.registered?(obj)
86
+ end
87
+
88
+ def get(obj)
89
+ registry.get(obj)
90
+ end
91
+
92
+ def put(obj, name)
93
+ registry.put(obj, name)
94
+ end
95
+
96
+ def names(filter_key = nil)
97
+ registry.names.keys
98
+ end
99
+
100
+ def print
101
+ registry.print
102
+ end
103
+
104
+ def registry
105
+ @@registry
106
+ end
52
107
 
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)
108
+ def reset(with_basic_types = true)
109
+ @@registry = Registry.new(with_basic_types)
66
110
  end
67
- @@registry
68
111
  end
69
112
  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)
@@ -5,17 +5,18 @@
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
  module Nameable
19
+ attr_accessor :name
18
20
  attr_accessor :names
19
- alias :name :names
20
21
  end
21
22
  end
@@ -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
@@ -37,53 +37,58 @@ module Bytemapper
37
37
  end
38
38
 
39
39
  def registered?(obj)
40
- names.key?(obj) || objects.key?(obj.hash)
40
+ v = registered_name?(obj) if obj.respond_to?(:to_sym)
41
+ v || registered_obj?(obj)
41
42
  end
42
43
 
43
- def get(obj, name = nil)
44
- if (obj.is_a?(String) || obj.is_a?(Symbol))
45
- # Object assumed to be a registered name
46
- obj = @objects.fetch(@names[obj])
47
- register_alias(obj, name) unless name.nil?
48
- elsif (obj.is_a?(Array) || obj.is_a?(Hash))
49
- obj = put(obj, name)
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)
50
50
  else
51
- raise ArgumentError "Invalid obj"
51
+ nil
52
52
  end
53
- obj
54
53
  end
55
54
 
56
55
  def put(obj, name = nil)
57
56
  obj = register_obj(obj)
58
- register_name(obj, name)
57
+ register_name(obj, name) unless name.nil?
59
58
  obj
60
59
  end
61
60
 
62
61
  def registered_name?(name)
63
- @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
64
68
  end
65
69
 
66
70
  def registered_obj?(obj)
67
- @objects.key?(obj.hash)
71
+ @objects.key?(obj.hash)
68
72
  end
69
73
 
70
74
  def register_obj(obj)
71
75
  unless registered_obj?(obj)
72
- obj.extend(Nameable)
73
- obj.names = Set.new
76
+ begin
77
+ obj.extend(Nameable)
78
+ obj.names = Set.new
79
+ rescue TypeError
80
+ end
74
81
  end
75
82
  @objects[obj.hash] ||= obj
76
83
  end
77
84
 
78
85
  def register_name(obj, name)
79
- unless name.nil?
80
- if registered_name?(name) && get(name) != obj
81
- raise ArgumentError.new 'Name is already registered'
82
- else
83
- name = name.to_sym
84
- @names[name] ||= obj.hash
85
- obj.names << name
86
- 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)
87
92
  end
88
93
  obj
89
94
  end
@@ -99,7 +104,7 @@ module Bytemapper
99
104
  # Buffer to build up output.
100
105
  buf = StringIO.new
101
106
 
102
- # Calculate the width of each column.
107
+ # Calculate the true max width of each column.
103
108
  widths = [
104
109
  @names.keys.size.zero? ? 0 : @names.keys.map(&:size).max + 1, # add space for the `:`
105
110
  7, # length of ID to print
@@ -107,6 +112,10 @@ module Bytemapper
107
112
  @objects.values.map { |v| v.to_s.size }.max
108
113
  ]
109
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
+
110
119
  # Add an extra space at the beginning and end of each column.
111
120
  widths = widths.map { |p| p += 2 }
112
121
 
@@ -127,21 +136,29 @@ module Bytemapper
127
136
 
128
137
  # Fixup the id string so it pads nicely
129
138
  idstr = id.positive? ? id.to_s[..5] : id.to_s[..6]
130
- idstr = id.positive? ? " #{idstr}" : " #{idstr}"
139
+ idstr = id.positive? ? " #{idstr}" : "#{idstr}"
131
140
 
132
- # Wrap each column value with whitespace.
141
+ # Generate the column values
133
142
  values = [
134
- name.empty? ? name : " :#{name} ",
135
- idstr,
136
- " #{obj.class.to_s} ",
137
- " #{obj.to_s} "
143
+ name.empty? ? name : ":#{name}",
144
+ idstr,
145
+ "#{obj.class.to_s}",
146
+ "#{obj.to_s}"
138
147
  ]
139
148
 
140
- # Calculate padding for each column.
141
- pads = widths.zip(values).map { |a,b| a - b.size }
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
142
159
 
143
160
  values.size.times do |i|
144
- buf << "#{values[i]}#{' '*pads[i]}|"
161
+ buf << "#{values[i]}|"
145
162
  end
146
163
  buf << "\n"
147
164
  end
@@ -164,18 +181,29 @@ module Bytemapper
164
181
  private
165
182
  def register_basic_types
166
183
  [
167
- [:char, [8,'c']],
168
- [:uchar, [8,'C']],
169
184
  [:uint8_t, [8,'C']],
185
+ [:u8, [8,'C']],
186
+ [:uchar, [8,'C']],
170
187
  [:bool, [8,'C']],
171
188
  [:uint16_t, [16,'S']],
189
+ [:u16, [16,'S']],
172
190
  [:uint32_t, [32,'L']],
191
+ [:u32, [32,'L']],
173
192
  [:uint64_t, [64,'Q']],
193
+ [:u64, [64,'Q']],
174
194
  [:int8_t, [8,'c']],
195
+ [:i8, [8,'c']],
196
+ [:char, [8,'c']],
175
197
  [:int16_t, [16,'s']],
198
+ [:i16, [16,'s']],
176
199
  [:int32_t, [32,'l']],
177
- [:int64_t, [64,'q']]
178
- ].each { |name, type| put(type, name) }
200
+ [:i32, [32,'l']],
201
+ [:int64_t, [64,'q']],
202
+ [:i64, [64,'q']]
203
+ ].each do |name, type|
204
+ type = Type.new(type)
205
+ put(type, name)
206
+ end
179
207
  end
180
208
  end
181
209
  end
@@ -0,0 +1,34 @@
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
+
30
+ def size
31
+ flatten.values.map(&:size).reduce(:+)
32
+ end
33
+ end
34
+ 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
@@ -0,0 +1,21 @@
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
+ module Typeable
19
+ attr_accessor :type
20
+ end
21
+ 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.16
4
+ version: 1.0.22
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-29 00:00:00.000000000 Z
11
+ date: 2020-06-14 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,9 @@ 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
26
+ - lib/bytemapper/typeable.rb
24
27
  homepage: https://github.com/l4cr0ss/bytemapper
25
28
  licenses:
26
29
  - AGPL-3.0-or-later