require "singleton" module VagrantPlugins module CommandServe class Mappers class ProcRegistry include Singleton def initialize @m = Mutex.new @stored = {} end def register(value) @m.synchronize do if !value.is_a?(Proc) raise TypeError, "Expected type `Proc' but received `#{value.class}'" end # If this is already stored, return existing ID idx = @stored.index(value) return idx if idx # Create a new ID and store id = SecureRandom.uuid @stored[id] = value id end end def fetch(idx) @m.synchronize do if !@stored.key?(idx) raise KeyError, "No `Proc' registered for given ID (#{idx})" end end @stored[idx] end end class ProcToProto < Mapper def initialize super( inputs: [ Input.new(type: Proc), ], output: SDK::Args::ProcRef, func: method(:converter), ) end def converter(value) SDK::Args::ProcRef.new( id: ProcRegistry.instance.register(value), ) end end class ProcFromProto < Mapper def initialize super( inputs: [ Input.new(type: SDK::Args::ProcRef), ], output: Proc, func: method(:converter) ) end def converter(proto) ProcRegistry.instance.fetch(proto.id) end end end end end