You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: unirpc.rb
    path of file: ./repos/metasploit-framework/lib/msf/core/exploit/remote
    
    the code of the file until where you have to start completion: # Encoding: ASCII-8BIT

module Msf
  class Exploit
    class Remote
      # Adapted from https://github.com/rbowes-r7/libneptune
      module Unirpc
        class UniRPCError < StandardError; end
        class UniRPCCommunicationError < UniRPCError; end
        class UniRPCUnexpectedResponseError < UniRPCError; end

        # This exception is caused by using illegal values in the module and
        # probably doesn't need to be caught
        class UniRPCUsageError < UniRPCError; end

        # Argument types
        UNIRPC_TYPE_INTEGER = 0
        UNIRPC_TYPE_FLOAT = 1
        UNIRPC_TYPE_STRING = 2
        UNIRPC_TYPE_BYTES = 3

   
    
        def build_unirpc_message(
          version_byte: 0x6c,
          other_version_byte: 0x01,
          body_length_override: nil,

          argcount_override: nil,

          body_override: nil,
          oldschool_data: '',
          args: [],

          skip_header: false
        )
          encrypt = datastore['UNIRPC_ENCODE_MESSAGES']

          # Ensure this is a string (in case the caller sets it to nil or something
          oldschool_data = oldschool_data.to_s

          # Allow the caller to override the body entirely, instead of packing
          # arguments
          if body_override
            body = body_override
          else
            # Pack the args at the start of the body - this is kinda metadata-ish
            body = args.map do |a|
              case a[:type]
              when :integer
                # Ints ignore the first value, and the second is always 0
                [a[:extra] || 0, UNIRPC_TYPE_INTEGER].pack('NN')
              when :string
                # Strings store the length in the first value, and the value in the body
                if a[:null_terminate].nil? || a[:null_terminate] == true
                  [a[:value].length + 1, UNIRPC_TYPE_STRING].pack('NN')
                else
                  [a[:value].length, UNIRPC_TYPE_STRING].pack('NN')
                end
              when :bytes
                # Bytes / rpcstrings store the length in the first value, and the value in the body
                [a[:value].length, UNIRPC_TYPE_BYTES].pack('NN')
              when :float
                # Floats ignore the first value, and the second value is the type
                [a[:extra] || 0, UNIRPC_TYPE_FLOAT].pack('NN')
              else
                raise(UniRPCUsageError, "Tried to build UniRPC packet with unknown type: #{a[:type]}")
              end