module JSON::ParserOptions

def array_class_proc(array_class, on_load)

def array_class_proc(array_class, on_load)
  ->(obj) do
    if Array === obj
      array = array_class.new
      obj.each { |v| array << v }
      obj = array
    end
    on_load.nil? ? obj : on_load.call(obj)
  end
end

def create_additions_proc(opts)

TODO: exctract :create_additions support to another gem for version 3.0
def create_additions_proc(opts)
  if opts[:symbolize_names]
    raise ArgumentError, "options :symbolize_names and :create_additions cannot be  used in conjunction"
  end
  opts = opts.dup
  create_additions = opts.fetch(:create_additions, false)
  on_load = opts[:on_load]
  object_class = opts[:object_class] || Hash
  opts[:on_load] = ->(object) do
    case object
    when String
      opts[:match_string]&.each do |pattern, klass|
        if match = pattern.match(object)
          create_additions_warning if create_additions.nil?
          object = klass.json_create(object)
          break
        end
      end
    when object_class
      if opts[:create_additions] != false
        if class_name = object[JSON.create_id]
          klass = JSON.deep_const_get(class_name)
          if (klass.respond_to?(:json_creatable?) && klass.json_creatable?) || klass.respond_to?(:json_create)
            create_additions_warning if create_additions.nil?
            object = klass.json_create(object)
          end
        end
      end
    end
    on_load.nil? ? object : on_load.call(object)
  end
  opts
end

def create_additions_warning

def create_additions_warning
  message = "JSON.load implicit support for `create_additions: true` is deprecated " \
    "and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
    "pass `create_additions: true`"
  uplevel = 4
  caller_locations(uplevel, 10).each do |frame|
    if frame.path.nil? || frame.path.start_with?(GEM_ROOT) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
      uplevel += 1
    else
      break
    end
  end
  if RUBY_VERSION >= "3.0"
    warn(message, uplevel: uplevel - 1, category: :deprecated)
  else
    warn(message, uplevel: uplevel - 1)
  end
end

def object_class_proc(object_class, on_load)

def object_class_proc(object_class, on_load)
  ->(obj) do
    if Hash === obj
      object = object_class.new
      obj.each { |k, v| object[k] = v }
      obj = object
    end
    on_load.nil? ? obj : on_load.call(obj)
  end
end

def prepare(opts)

def prepare(opts)
  if opts[:object_class] || opts[:array_class]
    opts = opts.dup
    on_load = opts[:on_load]
    on_load = object_class_proc(opts[:object_class], on_load) if opts[:object_class]
    on_load = array_class_proc(opts[:array_class], on_load) if opts[:array_class]
    opts[:on_load] = on_load
  end
  if opts.fetch(:create_additions, false) != false
    opts = create_additions_proc(opts)
  end
  opts
end