bytemapper 1.0.16 → 1.0.22

Sign up to get free protection for your applications and to get access to all the features.
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