module VagrantPlugins module CommandServe module Util module FuncSpec # Generate FuncSpec proto args based on provided spec # using given args # # @param spec [SDK::FuncSpec] Spec for function # @param args [Array] List of arguments to generate from # @return [SDK::FuncSpec::Args] def generate_funcspec_args(spec, *args) logger.trace("generating funcspec args for spec: #{spec}") if !spec.is_a?(SDK::FuncSpec) raise TypeError, "Expected `#{SDK::FuncSpec.name}' but received `#{spec.class.name}'" end m_args = args.dup if respond_to?(:seeds) m_args = m_args + seeds.typed.to_a + seeds.named.map { |name, val| val = mapper.unany(val) Type::NamedArgument.new( name: name, value: val, ) } end SDK::FuncSpec::Args.new( args: spec.args.map { |farg| logger.trace("starting funcspec generation for #{farg}") type = mapper.find_type(farg.type) gen = mapper.generate(*m_args, named: farg.name, type: type) logger.trace("generated value for type #{type.inspect} (name: #{farg.name.inspect}) -> #{gen}") any = Google::Protobuf::Any.pack(gen) SDK::FuncSpec::Value.new( type: any.type_name.split("/").last, value: any, name: farg.name, ) } ) end # Convert all given args to FuncSpec::Args proto # # @param extra [Array] Extra arguments to use during mapping # @param args [Array] Arguments to be mapped # @return [SDK::FuncSpec::Args] def to_funcspec(*args, extra: []) SDK::FuncSpec::Args.new( args: args.map { |arg| if arg.is_a?(Type::NamedArgument) name = arg.name arg = arg.value else name = "" end any = mapper.map(arg, *extra, to: Google::Protobuf::Any) SDK::FuncSpec::Value.new( name: name, type: any.type_name.split("/").last, value: any, ) } ) end # Call a defined func and execute the callback. # # @param name [String,Symbol] Name of method which provides a spec and callback # (defaults to name of caller method with `_func` suffix) # @param args [Array] Optional list of arguments def run_func(*args, name: nil, func_args: []) if name.nil? name = caller_locations.first.label.to_s if name.end_with?("!") || name.end_with?("?") name = name[0, name.length - 1] end name += "_func" end if !respond_to?(name) raise ArgumentError, "Class `#{self.class}' does not contain method `##{name}'" end logger.trace("running func #{name} for spec and callback") func_args = [name] + Array(func_args) spec, cb = send(*func_args) f_args = generate_funcspec_args(spec, *args) logger.trace("executing func #{name.sub(/_func$/, "")}") cb.call(f_args) end end end end end