bytemapper 1.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b7915e2b8be3bcd3f677ed08c5a82e8fd135ab941ff9ab8b04c2148cfc7b8441
4
+ data.tar.gz: c44bf0499a0d15dc77728770edf55a995a12b00987e76ea651eb249c09f0d2e7
5
+ SHA512:
6
+ metadata.gz: ea2aa731fde9ad3ef8f22a08d1b0abfa4de8803e7d7849af1ad1c0aebc9c865640e9e62f1ebc91293025c1b76b21cb5bd1b469d510005dead3a6723a6b4ef314
7
+ data.tar.gz: 9cbb50a69eea518d210ac6fb7bcaeeb9a74ff8b0e6ad3a9ade5f68988d6839c7d2464e9c276781d45fac856704de011352463c60a3b03d563ff90fec16ccf488
@@ -0,0 +1,69 @@
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/registry'
19
+ require 'bytemapper/nameable'
20
+ require 'bytemapper/flattenable'
21
+ require 'bytemapper/chunk'
22
+
23
+ @@registry = Registry.new
24
+
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) }
33
+ end
34
+ wrapper.extend(Flattenable)
35
+ obj = registry.put(wrapper, name)
36
+ else
37
+ raise ArgumentError.new "Invalid object"
38
+ end
39
+ obj
40
+ end
41
+
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
48
+
49
+ def self.registry
50
+ @@registry
51
+ end
52
+
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)
66
+ end
67
+ @@registry
68
+ end
69
+ end
@@ -0,0 +1,54 @@
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
+ class Chunk
19
+ attr_reader :bytes, :shape, :name
20
+
21
+ def initialize(bytes, shape, name)
22
+ @bytes = bytes
23
+ @shape = shape
24
+ @name = name
25
+
26
+ shape.flatten.each do |k,v|
27
+ singleton_class.instance_eval { attr_reader k }
28
+ instance_variable_set("@#{k.to_s}", unpack(v))
29
+ end
30
+ end
31
+
32
+ def string
33
+ bytes.string
34
+ end
35
+
36
+ def ord
37
+ bytes.string.split(//).map(&:ord)
38
+ end
39
+
40
+ def chr
41
+ bytes.string.split(//).map(&:chr)
42
+ end
43
+
44
+ def size
45
+ @bytes.size
46
+ end
47
+
48
+ def unpack(value, endian = nil)
49
+ num_bytes, flag = value
50
+ _bytes = bytes.read(num_bytes >> 3)
51
+ _bytes.unpack("#{flag}#{endian}")[0] unless _bytes.nil?
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,35 @@
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 Flattenable
19
+ def flatten(flattened = {}, prefix = nil)
20
+ each do |k,v|
21
+ k = prefix.nil? ? k : "#{prefix}_#{k}".to_sym
22
+ if v.is_a?(Hash)
23
+ v.flatten(flattened, k)
24
+ else
25
+ flattened[k] = v
26
+ end
27
+ end
28
+ flattened
29
+ end
30
+
31
+ def size
32
+ flatten.values.map(&:first).reduce(:+) >> 3
33
+ end
34
+ end
35
+ 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
+ module Bytemapper
17
+ module Nameable
18
+ attr_accessor :names
19
+ alias :name :names
20
+ end
21
+ end
@@ -0,0 +1,177 @@
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
+ module Bytemapper
17
+ class Registry
18
+ require 'bytemapper/nameable'
19
+
20
+ attr_reader :names
21
+ attr_reader :objects
22
+
23
+ def initialize(with_basic_types = true)
24
+ @objects = {}
25
+ @names = {}
26
+ register_basic_types unless with_basic_types == false
27
+ end
28
+
29
+ def empty?
30
+ @objects.size.zero? && @names.size.zero?
31
+ end
32
+
33
+ def flush
34
+ @objects = {}
35
+ @names = {}
36
+ end
37
+
38
+ def registered?(obj)
39
+ names.key?(obj) || objects.key?(obj.hash)
40
+ end
41
+
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
49
+ else
50
+ raise ArgumentError "Invalid obj"
51
+ end
52
+ @objects[key]
53
+ end
54
+
55
+ def put(obj, name = nil)
56
+ obj = register_obj(obj)
57
+ register_name(obj, name)
58
+ obj
59
+ end
60
+
61
+ def registered_name?(name)
62
+ @names.key?(name)
63
+ end
64
+
65
+ def registered_obj?(obj)
66
+ @objects.key?(obj.hash)
67
+ end
68
+
69
+ def register_obj(obj)
70
+ unless registered_obj?(obj)
71
+ obj.extend(Nameable)
72
+ obj.names = Set.new
73
+ end
74
+ @objects[obj.hash] ||= obj
75
+ end
76
+
77
+ 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
+ end
87
+ obj
88
+ end
89
+
90
+ def print
91
+ puts to_s
92
+ end
93
+
94
+ def to_s
95
+ return "" if @objects.empty?
96
+
97
+ # Buffer to build up output.
98
+ buf = StringIO.new
99
+
100
+ # Calculate the width of each column.
101
+ widths = [
102
+ @names.keys.size.zero? ? 0 : @names.keys.map(&:size).max + 1, # add space for the `:`
103
+ 7, # length of ID to print
104
+ @objects.values.map { |o| o.class.to_s.size }.max,
105
+ @objects.values.map { |v| v.to_s.size }.max
106
+ ]
107
+
108
+ # Add an extra space at the beginning and end of each column.
109
+ widths = widths.map { |p| p += 2 }
110
+
111
+ buf << "+"
112
+ # Build the header line.
113
+ widths.each do |w|
114
+ buf << "#{'-' * w}+"
115
+ end
116
+ buf << "\n"
117
+
118
+ # Build the rows of the table.
119
+ @objects.each do |id, obj|
120
+ names = @names.filter { |k,v| v == id }.keys
121
+ names << '' if names.empty?
122
+ # Create an entry for each object alias.
123
+ names.each do |name|
124
+ buf << "|"
125
+
126
+ # Fixup the id string so it pads nicely
127
+ idstr = id.positive? ? id.to_s[..5] : id.to_s[..6]
128
+ idstr = id.positive? ? " #{idstr}" : " #{idstr}"
129
+
130
+ # Wrap each column value with whitespace.
131
+ values = [
132
+ name.empty? ? name : " :#{name} ",
133
+ idstr,
134
+ " #{obj.class.to_s} ",
135
+ " #{obj.to_s} "
136
+ ]
137
+
138
+ # Calculate padding for each column.
139
+ pads = widths.zip(values).map { |a,b| a - b.size }
140
+
141
+ values.size.times do |i|
142
+ buf << "#{values[i]}#{' '*pads[i]}|"
143
+ end
144
+ buf << "\n"
145
+ end
146
+ end
147
+
148
+ # Build the trailing line.
149
+ buf << "+"
150
+ widths.each do |w|
151
+ buf << "#{'-' * w}+"
152
+ end
153
+ buf << "\n"
154
+ buf.string
155
+ end
156
+
157
+ def reset(with_basic_types = true)
158
+ flush
159
+ register_basic_types unless with_basic_types == false
160
+ end
161
+
162
+ private
163
+ def register_basic_types
164
+ [
165
+ [:uint8_t, [8,'C']],
166
+ [:bool, [8,'C']],
167
+ [:uint16_t, [16,'S']],
168
+ [:uint32_t, [32,'L']],
169
+ [:uint64_t, [64,'Q']],
170
+ [:int8_t, [8,'c']],
171
+ [:int16_t, [16,'s']],
172
+ [:int32_t, [32,'l']],
173
+ [:int64_t, [64,'q']]
174
+ ].each { |name, type| put(type, name) }
175
+ end
176
+ end
177
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bytemapper
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.13
5
+ platform: ruby
6
+ authors:
7
+ - Jefferson Hudson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-26 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Model and interact with bytestrings using Ruby objects.
14
+ email: jefferson.hudson@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/bytemapper.rb
20
+ - lib/bytemapper/chunk.rb
21
+ - lib/bytemapper/flattenable.rb
22
+ - lib/bytemapper/nameable.rb
23
+ - lib/bytemapper/registry.rb
24
+ homepage: https://github.com/l4cr0ss/bytemapper
25
+ licenses:
26
+ - AGPL-3.0-or-later
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubygems_version: 3.1.3
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: Map byte strings to Ruby objects
47
+ test_files: []