Add any unpacking. Filter blind maps.

This commit is contained in:
Chris Roberts 2021-10-29 09:03:07 -07:00 committed by Paul Hinze
parent 2712046a9d
commit 68ed3ba1d9
No known key found for this signature in database
GPG Key ID: B69DEDF2D55501C0

View File

@ -21,10 +21,15 @@ module VagrantPlugins
# available to all mapper calls
def initialize(*args)
@known_arguments = args
Mapper.generate_anys
@mappers = Mapper.registered.map(&:new)
@identifiers = []
end
def clone
n = self.class.new(*known_arguments)
end
# Add an argument to be included with mapping calls
#
# @param v [Object] Argument value
@ -55,6 +60,13 @@ module VagrantPlugins
thing.object_id.to_s
end
def unany(any)
type = any.type.split('/').last.to_s.split('.').inject(Object) { |memo, name|
memo.const_get(name.to_s.capitalize)
}
any.unpack(type)
end
# Map a given value
#
# @param value [Object] Value to map
@ -74,16 +86,37 @@ module VagrantPlugins
return val if val
end
if value.is_a?(Google::Protobuf::Any)
value = unany(value)
end
args = ([value] + extra_args + known_arguments).compact
result = nil
# For funcspec values, we want to pre-filter since they use
# a custom validator. This will prevent invalid paths.
if value.is_a?(SDK::FuncSpec::Value)
map_mapper = self.clone
valid_mappers = map_mapper.mappers.map do |m|
next if !m.inputs.first.valid?(SDK::FuncSpec::Value) &&
m.output.ancestors.include?(Google::Protobuf::MessageExts)
next m if !m.inputs.first.valid?(SDK::FuncSpec::Value) ||
m.inputs.first.valid?(value)
logger.warn("removing mapper - invalid funcspec match - #{m}")
nil
end.compact
map_mapper.mappers.replace(valid_mappers)
else
map_mapper = self
end
# If we don't have a desired final type, test for mappers
# that are satisfied by the arguments we have and run that
# directly
if to.nil?
valid_outputs = []
cb = lambda do |k|
matches = mappers.find_all do |m|
matches = map_mapper.mappers.find_all do |m|
m.inputs.first.valid?(k)
end
outs = matches.map(&:output)
@ -98,20 +131,21 @@ module VagrantPlugins
if valid_outputs.empty?
raise TypeError,
"No valid mappers found for input type `#{value.class}'"
"No valid mappers found for input type `#{value.class}' (#{value})"
end
valid_outputs.reverse!
logger.debug("mapper output types discovered for input type `#{value.class}': #{valid_outputs}")
logger.debug("mapper output types discovered for input type `#{value.class}': #{valid_outputs}, mappers:\n" + map_mapper.mappers.map(&:to_s).join("\n"))
last_error = nil
valid_outputs.each do |out|
begin
m_graph = Internal::Graph::Mappers.new(
output_type: out,
mappers: self,
mappers: map_mapper,
input_values: args,
)
result = m_graph.execute
break
rescue => err
logger.debug("typeless mapping failure (non-critical): #{err} (input - #{value} / output #{out})")
last_error = err
@ -121,12 +155,13 @@ module VagrantPlugins
else
m_graph = Internal::Graph::Mappers.new(
output_type: to,
mappers: self,
mappers: map_mapper,
input_values: args,
)
result = m_graph.execute
end
cacher[cache_key] = result if cacher
logger.debug("map of #{value} to #{to.inspect} => #{result}")
result
end
@ -140,10 +175,15 @@ module VagrantPlugins
# actual values
#
# @param spec [SDK::FuncSpec::Spec]
# @param expect [Array<Class>] Expected types for each argument
# @return [Array<Object>, Object]
def funcspec_map(spec, *extra_args)
result = spec.args.map do |arg|
map(arg, *extra_args)
def funcspec_map(spec, *extra_args, expect: [])
expect = Array(expect)
expect.unshift(expect.pop).compact
result = Array.new.tap do |result_args|
spec.args.each_with_index do |arg, i|
result_args << map(arg, *extra_args + result_args, to: expect[i])
end
end
if result.size == 1
return result.first