kaitai-struct-visualizer 0.7 → 0.11

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.
@@ -1,295 +1,302 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'kaitai/struct/visualizer/version'
2
4
 
3
5
  module Kaitai::Struct::Visualizer
4
- class HexViewer
5
- attr_accessor :shift_x
6
-
7
- def initialize(ui, buf, tree = nil)
8
- @ui = ui
9
- @buf = buf
10
- @shift_x = 0
11
- @tree = tree
12
-
13
- @embedded = not(tree.nil?)
14
- @max_scr_ln = @ui.rows - 3
15
-
16
- @addr = 0
17
- @scroll_y = 0
18
- reset_cur
19
- raise if @cur_x.nil?
20
- end
6
+ class HexViewer
7
+ attr_accessor :shift_x
21
8
 
22
- def buf=(buf)
23
- @buf = buf
24
- end
9
+ def initialize(ui, buf, tree = nil)
10
+ @ui = ui
11
+ @buf = buf
12
+ @shift_x = 0
13
+ @tree = tree
25
14
 
26
- def addr; @addr; end
27
- def addr=(a)
28
- @addr = a
29
- reset_cur
30
- end
15
+ @embedded = !tree.nil?
16
+ @max_scr_ln = @ui.rows - 3
31
17
 
32
- def reset_cur
33
- @cur_y = addr_to_row(@addr)
34
- @cur_x = addr_to_col(@addr)
35
- end
18
+ @addr = 0
19
+ @scroll_y = 0
20
+ reset_cur
21
+ raise if @cur_x.nil?
22
+ end
36
23
 
37
- def highlight(regions)
38
- highlight_hide
39
- @hl_regions = regions
40
- highlight_show
41
- end
24
+ attr_writer :buf
42
25
 
43
- def ensure_visible
44
- scr_y = row_to_scr(@cur_y)
45
- if scr_y < 0
46
- @scroll_y = @cur_y
47
- redraw
48
- highlight_show
49
- elsif scr_y > @max_scr_ln
50
- @scroll_y = @cur_y - @max_scr_ln
51
- redraw
26
+ attr_reader :addr
27
+
28
+ def addr=(a)
29
+ @addr = a
30
+ reset_cur
31
+ end
32
+
33
+ def reset_cur
34
+ @cur_y = addr_to_row(@addr)
35
+ @cur_x = addr_to_col(@addr)
36
+ end
37
+
38
+ def highlight(regions)
39
+ highlight_hide
40
+ @hl_regions = regions
52
41
  highlight_show
53
42
  end
54
- end
55
43
 
56
- def run
57
- c = nil
58
- loop {
59
- @ui.goto(0, @max_scr_ln + 1)
60
- printf "%08x (%d, %d)", @addr, @cur_x, @cur_y
61
-
62
- @ui.goto(col_to_col_char(@cur_x), row_to_scr(@cur_y))
63
- c = @ui.read_char_mapped
64
- case c
65
- when :tab
66
- return if @embedded
67
- when :left_arrow
68
- if @addr > 0
69
- @addr -= 1
70
- @cur_x -= 1
71
- if @cur_x < 0
72
- @cur_y -= 1
73
- @cur_x = PER_LINE - 1
44
+ def ensure_visible
45
+ scr_y = row_to_scr(@cur_y)
46
+ if scr_y.negative?
47
+ @scroll_y = @cur_y
48
+ redraw
49
+ highlight_show
50
+ elsif scr_y > @max_scr_ln
51
+ @scroll_y = @cur_y - @max_scr_ln
52
+ redraw
53
+ highlight_show
54
+ end
55
+ end
56
+
57
+ def run
58
+ c = nil
59
+ loop do
60
+ @ui.goto(0, @max_scr_ln + 1)
61
+ printf '%08x (%d, %d)', @addr, @cur_x, @cur_y
62
+
63
+ @ui.goto(col_to_col_char(@cur_x), row_to_scr(@cur_y))
64
+ c = @ui.read_char_mapped
65
+ case c
66
+ when :tab
67
+ return if @embedded
68
+ when :left_arrow
69
+ if @addr.positive?
70
+ @addr -= 1
71
+ @cur_x -= 1
72
+ if @cur_x.negative?
73
+ @cur_y -= 1
74
+ @cur_x = PER_LINE - 1
75
+ end
74
76
  end
75
- end
76
- when :right_arrow
77
- if @addr < @buf.size
78
- @addr += 1
79
- @cur_x += 1
80
- if @cur_x >= PER_LINE
81
- @cur_y += 1
77
+ when :right_arrow
78
+ if @addr < @buf.size
79
+ @addr += 1
80
+ @cur_x += 1
81
+ if @cur_x >= PER_LINE
82
+ @cur_y += 1
83
+ @cur_x = 0
84
+ end
85
+ end
86
+ when :up_arrow
87
+ @addr -= PER_LINE
88
+ @cur_y -= 1
89
+ clamp_cursor
90
+ when :down_arrow
91
+ @addr += PER_LINE
92
+ @cur_y += 1
93
+ clamp_cursor
94
+ when :pg_dn
95
+ @addr += PER_LINE * PAGE_ROWS
96
+ @cur_y += PAGE_ROWS
97
+ clamp_cursor
98
+ when :pg_up
99
+ @addr -= PER_LINE * PAGE_ROWS
100
+ @cur_y -= PAGE_ROWS
101
+ clamp_cursor
102
+ when :home
103
+ if @cur_x.zero?
104
+ @addr = 0
105
+ @cur_y = 0
106
+ else
107
+ @addr -= @cur_x
82
108
  @cur_x = 0
83
109
  end
110
+ clamp_cursor
111
+ when :end
112
+ if @cur_x == PER_LINE - 1
113
+ @addr = @buf.size - 1
114
+ reset_cur
115
+ else
116
+ @addr = @addr - @cur_x + PER_LINE - 1
117
+ @cur_x = PER_LINE - 1
118
+ end
119
+ clamp_cursor
120
+ when 'w'
121
+ fn = @ui.input_str('Write buffer to file', 'Filename')
122
+ File.open(fn, 'w') do |out|
123
+ out.write(@buf)
124
+ end
125
+ @ui.clear
126
+ redraw
127
+ when 'q'
128
+ @tree&.do_exit
129
+ return
84
130
  end
85
- when :up_arrow
86
- @addr -= PER_LINE
87
- @cur_y -= 1
88
- clamp_cursor
89
- when :down_arrow
90
- @addr += PER_LINE
91
- @cur_y += 1
92
- clamp_cursor
93
- when :pg_dn
94
- @addr += PER_LINE * PAGE_ROWS
95
- @cur_y += PAGE_ROWS
96
- clamp_cursor
97
- when :pg_up
98
- @addr -= PER_LINE * PAGE_ROWS
99
- @cur_y -= PAGE_ROWS
100
- clamp_cursor
101
- when :home
102
- if @cur_x == 0
103
- @addr = 0
104
- @cur_y = 0
105
- else
106
- @addr -= @cur_x
107
- @cur_x = 0
108
- end
109
- clamp_cursor
110
- when :end
111
- if @cur_x == PER_LINE - 1
112
- @addr = @buf.size - 1
113
- reset_cur
114
- else
115
- @addr = @addr - @cur_x + PER_LINE - 1
116
- @cur_x = PER_LINE - 1
117
- end
118
- clamp_cursor
119
- when 'w'
120
- fn = @ui.input_str('Write buffer to file', 'Filename')
121
- File.open(fn, 'w') { |out|
122
- out.write(@buf)
123
- }
124
- @ui.clear
125
- redraw
126
- when 'q'
127
- @tree.do_exit if @tree
128
- return
129
- end
130
131
 
131
- ensure_visible
132
- }
133
- end
132
+ ensure_visible
133
+ end
134
+ end
134
135
 
135
- def clamp_cursor
136
- if @addr < 0
137
- @addr = 0
138
- @cur_x = 0
139
- @cur_y = 0
140
- elsif @addr >= @buf.size
141
- @addr = @buf.size - 1
142
- reset_cur
136
+ def clamp_cursor
137
+ if @addr.negative?
138
+ @addr = 0
139
+ @cur_x = 0
140
+ @cur_y = 0
141
+ elsif @addr >= @buf.size
142
+ @addr = @buf.size - 1
143
+ reset_cur
144
+ end
143
145
  end
144
- end
145
146
 
146
- PER_LINE = 16
147
- PER_GROUP = 4
148
- PAGE_ROWS = 20
149
- FMT = "%08x: %-#{PER_LINE * 3}s| %-#{PER_LINE}s\n"
147
+ PER_LINE = 16
148
+ PER_GROUP = 4
149
+ PAGE_ROWS = 20
150
+ FMT = "%08x: %-#{PER_LINE * 3}s| %-#{PER_LINE}s\n"
150
151
 
151
- def self.line_width
152
- #8 + 2 + 3 * PER_LINE + 2 + PER_LINE
153
- 12 + 4 * PER_LINE
154
- end
152
+ def self.line_width
153
+ # 8 + 2 + 3 * PER_LINE + 2 + PER_LINE
154
+ 12 + 4 * PER_LINE
155
+ end
155
156
 
156
- def col_to_col_hex(c)
157
- #8 + 2 + 3 * c
158
- @shift_x + 10 + 3 * c
159
- end
157
+ def col_to_col_hex(c)
158
+ # 8 + 2 + 3 * c
159
+ @shift_x + 10 + 3 * c
160
+ end
160
161
 
161
- def col_to_col_char(c)
162
- #8 + 2 + 3 * PER_LINE + 2
163
- @shift_x + 12 + 3 * PER_LINE + c
164
- end
162
+ def col_to_col_char(c)
163
+ # 8 + 2 + 3 * PER_LINE + 2
164
+ @shift_x + 12 + 3 * PER_LINE + c
165
+ end
165
166
 
166
- def row_to_scr(r)
167
- r - @scroll_y
168
- end
167
+ def row_to_scr(r)
168
+ r - @scroll_y
169
+ end
169
170
 
170
- def redraw
171
- i = row_col_to_addr(@scroll_y, 0)
172
- row = 0
171
+ def redraw
172
+ i = row_col_to_addr(@scroll_y, 0)
173
+ row = 0
173
174
 
174
- while row <= @max_scr_ln do
175
- line = @buf[i, PER_LINE]
176
- return unless line
175
+ while row <= @max_scr_ln
176
+ line = @buf[i, PER_LINE]
177
+ return unless line
177
178
 
178
- @ui.goto(@shift_x, row)
179
+ @ui.goto(@shift_x, row)
179
180
 
180
- hex = line.bytes.map { |x| sprintf('%02x', x) }.join(' ')
181
- char = line.bytes.map { |x| byte_to_display_char(x) }.join
181
+ hex = line.bytes.map { |x| format('%02x', x) }.join(' ')
182
+ char = line.bytes.map { |x| byte_to_display_char(x) }.join
182
183
 
183
- printf FMT, i, hex, char
184
- i += PER_LINE
185
- row += 1
184
+ printf FMT, i, hex, char
185
+ i += PER_LINE
186
+ row += 1
187
+ end
186
188
  end
187
- end
188
189
 
189
- def each_highlight_region
190
- return if @hl_regions.nil?
191
- n = @hl_regions.size
192
- (n - 1).downto(0).each { |i|
193
- p1 = @hl_regions[i][0]
194
- p2 = @hl_regions[i][1]
195
- yield i, p1, p2 unless p1.nil?
196
- }
197
- end
190
+ def each_highlight_region
191
+ return if @hl_regions.nil?
198
192
 
199
- def highlight_hide
200
- each_highlight_region { |i, p1, p2|
201
- highlight_draw(p1, p2)
202
- }
203
- end
193
+ n = @hl_regions.size
194
+ (n - 1).downto(0).each do |i|
195
+ p1 = @hl_regions[i][0]
196
+ p2 = @hl_regions[i][1]
197
+ yield i, p1, p2 unless p1.nil?
198
+ end
199
+ end
204
200
 
205
- def highlight_show
206
- each_highlight_region { |i, p1, p2|
207
- @ui.bg_color = @ui.highlight_colors[i]
208
- @ui.fg_color = :black
209
- highlight_draw(p1, p2)
210
- }
211
- @ui.reset_colors
212
- end
201
+ def highlight_hide
202
+ each_highlight_region do |_i, p1, p2|
203
+ highlight_draw(p1, p2)
204
+ end
205
+ end
213
206
 
214
- def highlight_draw(p1, p2)
215
- r = row_to_scr(addr_to_row(p1))
216
- return if r > @max_scr_ln
217
- if r < 0
218
- c = 0
219
- r = 0
220
- i = row_col_to_addr(@scroll_y, 0)
221
- return if i >= p2
222
- else
223
- c = addr_to_col(p1)
224
- i = p1
207
+ def highlight_show
208
+ each_highlight_region do |i, p1, p2|
209
+ @ui.bg_color = @ui.highlight_colors[i]
210
+ @ui.fg_color = :black
211
+ highlight_draw(p1, p2)
212
+ end
213
+ @ui.reset_colors
225
214
  end
226
215
 
227
- highlight_draw_hex(r, c, i, p2)
228
- highlight_draw_char(r, c, i, p2)
229
- end
216
+ def highlight_draw(p1, p2)
217
+ r = row_to_scr(addr_to_row(p1))
218
+ return if r > @max_scr_ln
230
219
 
231
- def highlight_draw_hex(r, c, i, p2)
232
- @ui.goto(col_to_col_hex(c), r)
233
- while i < p2
234
- v = byte_at(i)
235
- return if v.nil?
236
- printf('%02x ', v)
237
- c += 1
238
- if c >= PER_LINE
220
+ if r.negative?
239
221
  c = 0
240
- r += 1
241
- return if r > @max_scr_ln
242
- @ui.goto(col_to_col_hex(c), r)
222
+ r = 0
223
+ i = row_col_to_addr(@scroll_y, 0)
224
+ return if i >= p2
225
+ else
226
+ c = addr_to_col(p1)
227
+ i = p1
243
228
  end
244
- i += 1
229
+
230
+ highlight_draw_hex(r, c, i, p2)
231
+ highlight_draw_char(r, c, i, p2)
245
232
  end
246
- end
247
233
 
248
- def highlight_draw_char(r, c, i, p2)
249
- @ui.goto(col_to_col_char(c), r)
234
+ def highlight_draw_hex(r, c, i, p2)
235
+ @ui.goto(col_to_col_hex(c), r)
236
+ while i < p2
237
+ v = byte_at(i)
238
+ return if v.nil?
250
239
 
251
- while i < p2
252
- v = byte_at(i)
253
- return if v.nil?
254
- print byte_to_display_char(v)
255
- c += 1
256
- if c >= PER_LINE
257
- c = 0
258
- r += 1
259
- return if r > @max_scr_ln
260
- @ui.goto(col_to_col_char(c), r)
240
+ printf('%02x ', v)
241
+ c += 1
242
+ if c >= PER_LINE
243
+ c = 0
244
+ r += 1
245
+ return if r > @max_scr_ln
246
+
247
+ @ui.goto(col_to_col_hex(c), r)
248
+ end
249
+ i += 1
261
250
  end
262
- i += 1
263
251
  end
264
- end
265
252
 
266
- def byte_at(i)
267
- v = @buf[i]
268
- if v.nil?
269
- nil
270
- else
271
- v.ord
253
+ def highlight_draw_char(r, c, i, p2)
254
+ @ui.goto(col_to_col_char(c), r)
255
+
256
+ while i < p2
257
+ v = byte_at(i)
258
+ return if v.nil?
259
+
260
+ print byte_to_display_char(v)
261
+ c += 1
262
+ if c >= PER_LINE
263
+ c = 0
264
+ r += 1
265
+ return if r > @max_scr_ln
266
+
267
+ @ui.goto(col_to_col_char(c), r)
268
+ end
269
+ i += 1
270
+ end
271
+ end
272
+
273
+ def byte_at(i)
274
+ v = @buf[i]
275
+ if v.nil?
276
+ nil
277
+ else
278
+ v.ord
279
+ end
272
280
  end
273
- end
274
281
 
275
- def byte_to_display_char(x)
276
- if x < 0x20 or x >= 0x7f
277
- '.'
278
- else
279
- x.chr
282
+ def byte_to_display_char(x)
283
+ if (x < 0x20) || (x >= 0x7f)
284
+ '.'
285
+ else
286
+ x.chr
287
+ end
280
288
  end
281
- end
282
289
 
283
- def addr_to_row(addr)
284
- addr / PER_LINE
285
- end
290
+ def addr_to_row(addr)
291
+ addr / PER_LINE
292
+ end
286
293
 
287
- def addr_to_col(addr)
288
- addr % PER_LINE
289
- end
294
+ def addr_to_col(addr)
295
+ addr % PER_LINE
296
+ end
290
297
 
291
- def row_col_to_addr(row, col)
292
- row * PER_LINE + col
298
+ def row_col_to_addr(row, col)
299
+ row * PER_LINE + col
300
+ end
293
301
  end
294
302
  end
295
- end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kaitai/struct/struct'
4
+
5
+ module Kaitai::Struct::Visualizer
6
+ class KSErrorMatcher
7
+ def self.===(exc)
8
+ return true if exc.is_a?(EOFError)
9
+ return true if exc.is_a?(ArgumentError)
10
+ return true if exc.is_a?(NoMethodError)
11
+ return true if exc.is_a?(TypeError)
12
+
13
+ # Raised by the runtime library's seek() implementation for negative offsets, see
14
+ # https://github.com/kaitai-io/kaitai_struct_ruby_runtime/blob/0fa62e64949f68cb001b58b7b45e15580d154ac9/lib/kaitai/struct/struct.rb#L637
15
+ return true if exc.is_a?(Errno::EINVAL)
16
+
17
+ # KaitaiStructError is a common ancestor of all Validation*Error and
18
+ # UndecidedEndiannessError classes since 0.9. However, it doesn't exist in
19
+ # the runtime library before 0.9, so we first make sure it's defined
20
+ # before we access it (accessing an undefined item would result in a
21
+ # NameError).
22
+ return true if
23
+ defined?(Kaitai::Struct::KaitaiStructError) &&
24
+ exc.is_a?(Kaitai::Struct::KaitaiStructError)
25
+ # Since 0.9, UndecidedEndiannessError is a subclass of KaitaiStructError
26
+ # (which was already handled above), but in 0.8 it was derived directly
27
+ # from Exception (in which case it hasn't been handled yet). Also,
28
+ # switchable default endianness is a new feature in 0.8, so the
29
+ # UndecidedEndiannessError class doesn't exist in older runtimes at all.
30
+ return true if
31
+ defined?(Kaitai::Struct::Stream::UndecidedEndiannessError) &&
32
+ exc.is_a?(Kaitai::Struct::Stream::UndecidedEndiannessError)
33
+ # UnexpectedDataError is no longer thrown by KSC-generated code since 0.9 -
34
+ # it has been superseded by ValidationNotEqualError. It still exists
35
+ # even in the 0.10 runtime library, but it will be removed one day, so
36
+ # we'll also check if it's defined.
37
+ return true if
38
+ defined?(Kaitai::Struct::Stream::UnexpectedDataError) &&
39
+ exc.is_a?(Kaitai::Struct::Stream::UnexpectedDataError)
40
+
41
+ false
42
+ end
43
+ end
44
+ end