canvas-lms/lib/dump_helper.rb

60 lines
1.9 KiB
Ruby

# frozen_string_literal: true
require 'set'
module DumpHelper
class << self
def find_dump_error(val, key = "<toplevel>", prefix = "", __visited_dump_vars = Set.new)
return if __visited_dump_vars.include?(val)
__visited_dump_vars << val
Marshal.dump(val)
rescue TypeError
if $!.message == "singleton can't be dumped" && !val.singleton_methods.empty?
raise TypeError, "Unable to dump #{prefix}#{key} (#<#{val.class}>): #{$!}"
end
# see if anything inside val can't be dumped...
sub_prefix = " #{prefix}#{key} (#<#{val.class}>) => "
if val.respond_to?(:marshal_dump, true)
return find_dump_error(val.marshal_dump, "marshal_dump", sub_prefix, __visited_dump_vars)
elsif val.respond_to?(:_dump, true)
stringval = val._dump(-1)
unless stringvals.instance_variables.empty?
dump_ivars(stringval, "#{sub_prefix}_dump => ", __visited_dump_vars)
else
dump_ivars(val, sub_prefix, __visited_dump_vars)
end
return
else
dump_ivars(val, sub_prefix, __visited_dump_vars)
if val.is_a?(Hash) || val.is_a?(Struct)
val.each_pair do |k, v|
find_dump_error(k, "hash key #{k}", sub_prefix, __visited_dump_vars)
find_dump_error(v, "[#{k.inspect}]", sub_prefix, __visited_dump_vars)
end
elsif val.is_a?(Array)
val.each_with_index do |v, i|
find_dump_error(v, "[#{i}]", sub_prefix, __visited_dump_vars)
end if val.is_a?(Array)
else
# guess it's val proper
raise TypeError.new("Unable to dump #{prefix}#{key} (#<#{val.class}>): #{$!}")
end
end
end
private
def dump_ivars(val, sub_prefix, __visited_dump_vars)
val.instance_variables.map do |k|
v = val.instance_variable_get(k)
find_dump_error(v, k, sub_prefix, __visited_dump_vars)
end
end
end
end