bytemapper 1.0.13

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.
@@ -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: []