# frozen_string_literal: truerequire"time"require"base64"require"bigdecimal"require"bigdecimal/util"require"active_support/core_ext/module/delegation"require"active_support/core_ext/string/inflections"require"active_support/core_ext/date_time/calculations"moduleActiveSupport# = \XmlMini## To use the much faster libxml parser:# gem 'libxml-ruby'# XmlMini.backend = 'LibXML'moduleXmlMiniextendself# This module decorates files deserialized using Hash.from_xml with# the <tt>original_filename</tt> and <tt>content_type</tt> methods.moduleFileLike# :nodoc:attr_writer:original_filename,:content_typedeforiginal_filename@original_filename||"untitled"enddefcontent_type@content_type||"application/octet-stream"endendDEFAULT_ENCODINGS={"binary"=>"base64"}unlessdefined?(DEFAULT_ENCODINGS)unlessdefined?(TYPE_NAMES)TYPE_NAMES={"Symbol"=>"symbol","Integer"=>"integer","BigDecimal"=>"decimal","Float"=>"float","TrueClass"=>"boolean","FalseClass"=>"boolean","Date"=>"date","DateTime"=>"dateTime","Time"=>"dateTime","Array"=>"array","Hash"=>"hash"}endTYPE_NAMES["ActiveSupport::TimeWithZone"]=TYPE_NAMES["Time"]FORMATTING={"symbol"=>Proc.new{|symbol|symbol.to_s},"date"=>Proc.new{|date|date.to_fs(:db)},"dateTime"=>Proc.new{|time|time.xmlschema},"binary"=>Proc.new{|binary|::Base64.encode64(binary)},"yaml"=>Proc.new{|yaml|yaml.to_yaml}}unlessdefined?(FORMATTING)# TODO use regexp instead of Date.parseunlessdefined?(PARSING)PARSING={"symbol"=>Proc.new{|symbol|symbol.to_s.to_sym},"date"=>Proc.new{|date|::Date.parse(date)},"datetime"=>Proc.new{|time|Time.xmlschema(time).utcrescue::DateTime.parse(time).utc},"integer"=>Proc.new{|integer|integer.to_i},"float"=>Proc.new{|float|float.to_f},"decimal"=>Proc.newdo|number|ifString===numbernumber.to_delseBigDecimal(number)endend,"boolean"=>Proc.new{|boolean|%w(1 true).include?(boolean.to_s.strip)},"string"=>Proc.new{|string|string.to_s},"yaml"=>Proc.new{|yaml|YAML.load(yaml)rescueyaml},"base64Binary"=>Proc.new{|bin|::Base64.decode64(bin)},"binary"=>Proc.new{|bin,entity|_parse_binary(bin,entity)},"file"=>Proc.new{|file,entity|_parse_file(file,entity)}}PARSING.update("double"=>PARSING["float"],"dateTime"=>PARSING["datetime"])endattr_accessor:depthself.depth=100delegate:parse,to: :backenddefbackendcurrent_thread_backend||@backendenddefbackend=(name)backend=name&&cast_backend_name_to_module(name)self.current_thread_backend=backendifcurrent_thread_backend@backend=backendenddefwith_backend(name)old_backend=current_thread_backendself.current_thread_backend=name&&cast_backend_name_to_module(name)yieldensureself.current_thread_backend=old_backendenddefto_tag(key,value,options)type_name=options.delete(:type)merged_options=options.merge(root: key,skip_instruct: true)ifvalue.is_a?(::Method)||value.is_a?(::Proc)ifvalue.arity==1value.call(merged_options)elsevalue.call(merged_options,key.to_s.singularize)endelsifvalue.respond_to?(:to_xml)value.to_xml(merged_options)elsetype_name||=TYPE_NAMES[value.class.name]type_name||=value.class.nameifvalue&&!value.respond_to?(:to_str)type_name=type_name.to_siftype_nametype_name="dateTime"iftype_name=="datetime"key=rename_key(key.to_s,options)attributes=options[:skip_types]||type_name.nil??{}:{type: type_name}attributes[:nil]=trueifvalue.nil?encoding=options[:encoding]||DEFAULT_ENCODINGS[type_name]attributes[:encoding]=encodingifencodingformatted_value=FORMATTING[type_name]&&!value.nil??FORMATTING[type_name].call(value):valueoptions[:builder].tag!(key,formatted_value,attributes)endenddefrename_key(key,options={})camelize=options[:camelize]dasherize=!options.has_key?(:dasherize)||options[:dasherize]ifcamelizekey=true==camelize?key.camelize:key.camelize(camelize)endkey=_dasherize(key)ifdasherizekeyendprivatedef_dasherize(key)# $2 must be a non-greedy regex for this to workleft,middle,right=/\A(_*)(.*?)(_*)\Z/.match(key.strip)[1,3]"#{left}#{middle.tr('_ ','--')}#{right}"end# TODO: Add support for other encodingsdef_parse_binary(bin,entity)caseentity["encoding"]when"base64"::Base64.decode64(bin)elsebinendenddef_parse_file(file,entity)f=StringIO.new(::Base64.decode64(file))f.extend(FileLike)f.original_filename=entity["name"]f.content_type=entity["content_type"]fenddefcurrent_thread_backendIsolatedExecutionState[:xml_mini_backend]enddefcurrent_thread_backend=(name)IsolatedExecutionState[:xml_mini_backend]=name&&cast_backend_name_to_module(name)enddefcast_backend_name_to_module(name)ifname.is_a?(Module)nameelserequire"active_support/xml_mini/#{name.downcase}"ActiveSupport.const_get("XmlMini_#{name}")endendendXmlMini.backend="REXML"end