# frozen_string_literal: truemoduleTurbopuffermoduleInternalmoduleType# @api private## @example# # `attribute_schema` is a `Turbopuffer::AttributeSchema`# case attribute_schema# when Turbopuffer::AttributeType# # ...# when Turbopuffer::AttributeSchemaConfig# puts(attribute_schema.ann)# else# puts(attribute_schema)# endmoduleUnionincludeTurbopuffer::Internal::Type::ConverterincludeTurbopuffer::Internal::Util::SorbetRuntimeSupport# @api private## All of the specified variant info for this union.## @return [Array<Array(Symbol, Proc)>]privatedefknown_variants=(@known_variants||=[])# @api private## @return [Array<Array(Symbol, Object)>]protecteddefderefed_variantsknown_variants.map{|key,variant_fn|[key,variant_fn.call]}end# All of the specified variants for this union.## @return [Array<Object>]defvariants=derefed_variants.map(&:last)# @api private## @param property [Symbol]privatedefdiscriminator(property)casepropertyinSymbol@discriminator=propertyendend# @api private## @param key [Symbol, Hash{Symbol=>Object}, Proc, Turbopuffer::Internal::Type::Converter, Class]## @param spec [Hash{Symbol=>Object}, Proc, Turbopuffer::Internal::Type::Converter, Class] .## @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const## @option spec [Proc] :enum## @option spec [Proc] :union## @option spec [Boolean] :"nil?"privatedefvariant(key,spec=nil)variant_info=casekeyinSymbol[key,Turbopuffer::Internal::Type::Converter.type_info(spec)]inProc|Turbopuffer::Internal::Type::Converter|Class|Hash[nil,Turbopuffer::Internal::Type::Converter.type_info(key)]endknown_variants<<variant_infoend# @api private## @param value [Object]## @return [Turbopuffer::Internal::Type::Converter, Class, nil]privatedefresolve_variant(value)case[@discriminator,value]in[_,Turbopuffer::Internal::Type::BaseModel]value.classin[Symbol,Hash]key=value.fetch(@discriminator)dovalue.fetch(@discriminator.to_s,Turbopuffer::Internal::OMIT)endreturnnilifkey==Turbopuffer::Internal::OMITkey=key.to_symifkey.is_a?(String)known_variants.find{|k,|k==key}&.last&.callelsenilendend# rubocop:disable Style/HashEachMethods# rubocop:disable Style/CaseEquality# @api public## @param other [Object]## @return [Boolean]def===(other)known_variants.any?do|_,variant_fn|variant_fn.call===otherendend# @api public## @param other [Object]## @return [Boolean]def==(other)Turbopuffer::Internal::Type::Union===other&&other.derefed_variants==derefed_variantsend# @api public## @return [Integer]defhash=variants.hash# @api private## Tries to efficiently coerce the given value to one of the known variants.## If the value cannot match any of the known variants, the coercion is considered# non-viable and returns the original value.## @param value [Object]## @param state [Hash{Symbol=>Object}] .## @option state [Boolean] :translate_names## @option state [Boolean] :strictness## @option state [Hash{Symbol=>Object}] :exactness## @option state [Class<StandardError>] :error## @option state [Integer] :branched## @return [Object]defcoerce(value,state:)if(target=resolve_variant(value))returnTurbopuffer::Internal::Type::Converter.coerce(target,value,state: state)endstrictness=state.fetch(:strictness)exactness=state.fetch(:exactness)alternatives=[]known_variants.eachdo|_,variant_fn|target=variant_fn.callexact=state[:exactness]={yes: 0,no: 0,maybe: 0}state[:branched]+=1coerced=Turbopuffer::Internal::Type::Converter.coerce(target,value,state: state)yes,no,maybe=exact.valuesif(no+maybe).zero?||(!strictness&&yes.positive?)exact.each{exactness[_1]+=_2}state[:exactness]=exactnessreturncoercedelsifmaybe.positive?alternatives<<[[-yes,-maybe,no],exact,coerced]endendcasealternatives.sort_by!(&:first)in[]exactness[:no]+=1state[:error]=ArgumentError.new("no matching variant for #{value.inspect}")valuein[[_,exact,coerced],*]exact.each{exactness[_1]+=_2}coercedend.tap{state[:exactness]=exactness}ensurestate[:strictness]=strictnessend# @api private## @param value [Object]## @param state [Hash{Symbol=>Object}] .## @option state [Boolean] :can_retry## @return [Object]defdump(value,state:)if(target=resolve_variant(value))returnTurbopuffer::Internal::Type::Converter.dump(target,value,state: state)endknown_variants.eachdotarget=_2.calliftarget===valuereturnTurbopuffer::Internal::Type::Converter.dump(target,value,state: state)endendsuperend# @api private## @return [Object]defto_sorbet_typetypes=variants.map{Turbopuffer::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(_1)}.uniqcasetypesin[]T.noreturnin[type]typeelseT.any(*types)endend# rubocop:enable Style/CaseEquality# rubocop:enable Style/HashEachMethods# @api private## @param depth [Integer]## @return [String]definspect(depth: 0)ifdepth.positive?returnis_a?(Module)?super():self.class.nameendmembers=variants.map{Turbopuffer::Internal::Type::Converter.inspect(_1,depth: depth.succ)}prefix=is_a?(Module)?name:self.class.name"#{prefix}[#{members.join(' | ')}]"endendendendend