lib/bindata/trace.rb
module BinData # Turn on trace information when reading a BinData object. # If +block+ is given then the tracing only occurs for that block. # This is useful for debugging a BinData declaration. def trace_reading(io = STDERR) @tracer = Tracer.new(io) [BasePrimitive, Choice].each(&:turn_on_tracing) if block_given? begin yield ensure [BasePrimitive, Choice].each(&:turn_off_tracing) @tracer = nil end end end # reference to the current tracer @tracer ||= nil class Tracer # :nodoc: def initialize(io) @trace_io = io end def trace(msg) @trace_io.puts(msg) end def trace_obj(obj_name, val) if val.length > 30 val = val.slice(0..30) + "..." end trace "#{obj_name} => #{val}" end end def trace_message # :nodoc: yield @tracer end module_function :trace_reading, :trace_message module TraceHook def turn_on_tracing if !method_defined? :do_read_without_hook alias_method :do_read_without_hook, :do_read alias_method :do_read, :do_read_with_hook end end def turn_off_tracing if method_defined? :do_read_without_hook alias_method :do_read, :do_read_without_hook remove_method :do_read_without_hook end end end class BasePrimitive < BinData::Base extend TraceHook def do_read_with_hook(io) do_read_without_hook(io) BinData.trace_message do |tracer| value_string = _value.inspect tracer.trace_obj(debug_name, value_string) end end end class Choice < BinData::Base extend TraceHook def do_read_with_hook(io) BinData.trace_message do |tracer| selection_string = eval_parameter(:selection).inspect tracer.trace_obj("#{debug_name}-selection-", selection_string) end do_read_without_hook(io) end end end