docs: def build_rule(table=None, chain=None, command=None, position='', full=None, family='ipv4',
                 **kwargs):
      '''
      Build a well-formatted nftables rule based on kwargs.
      A `table` and `chain` are not required, unless `full` is True.
  
      If `full` is `True`, then `table`, `chain` and `command` are required.
      `command` may be specified as either insert, append, or delete.
      This will return the nftables command, exactly as it would
      be used from the command line.
  
      If a position is required (as with `insert` or `delete`), it may be specified as
      `position`. This will only be useful if `full` is True.
  
      If `connstate` is passed in, it will automatically be changed to `state`.
  
      CLI Examples:
  
      .. code-block:: bash
  
          salt '*' nftables.build_rule match=state \\
              connstate=RELATED,ESTABLISHED jump=ACCEPT
          salt '*' nftables.build_rule filter input command=insert position=3 \\
              full=True match=state state=related,established jump=accept
  
          IPv6:
          salt '*' nftables.build_rule match=state \\
              connstate=related,established jump=accept \\
              family=ipv6
          salt '*' nftables.build_rule filter input command=insert position=3 \\
              full=True match=state state=related,established jump=accept \\
              family=ipv6
  
      '''
      ret = {'comment': '',
             'rule': '',
             'result': False}
  
      if 'target' in kwargs:
          kwargs['jump'] = kwargs['target']
          del kwargs['target']
  
      for ignore in list(_STATE_INTERNAL_KEYWORDS) + ['chain', 'save', 'table']:
          if ignore in kwargs:
              del kwargs[ignore]
  
      rule = ''
      proto = ''
  
      nft_family = _NFTABLES_FAMILIES[family]
  
      if 'if' in kwargs:
          rule += 'meta iifname {0} '.format(kwargs['if'])
          del kwargs['if']
  
      if 'of' in kwargs:
          rule += 'meta oifname {0} '.format(kwargs['of'])
          del kwargs['of']
  
      if 'proto' in kwargs:
          proto = kwargs['proto']
  
      if 'state' in kwargs:
          del kwargs['state']
  
      if 'connstate' in kwargs:
          rule += 'ct state {{ {0}}} '.format(kwargs['connstate'])
          del kwargs['connstate']
  
      if 'dport' in kwargs:
          kwargs['dport'] = six.text_type(kwargs['dport'])
          if ':' in kwargs['dport']:
              kwargs['dport'] = kwargs['dport'].replace(':', '-')
          rule += 'dport {{ {0} }} '.format(kwargs['dport'])
          del kwargs['dport']
  
      if 'sport' in kwargs:
          kwargs['sport'] = six.text_type(kwargs['sport'])
          if ':' in kwargs['sport']:
              kwargs['sport'] = kwargs['sport'].replace(':', '-')
          rule += 'sport {{ {0} }} '.format(kwargs['sport'])
          del kwargs['sport']
  
      if 'dports' in kwargs:
          # nftables reverse sorts the ports from
          # high to low, create rule like this
          # so that the check will work
          _dports = kwargs['dports'].split(',')
          _dports = [int(x) for x in _dports]
          _dports.sort(reverse=True)
          kwargs['dports'] = ', '.join(six.text_type(x) for x in _dports)
  
          rule += 'dport {{ {0} }} '.format(kwargs['dports'])
          del kwargs['dports']
  
      if 'sports' in kwargs:
          # nftables reverse sorts the ports from
          # high to low, create rule like this
          # so that the check will work
          _sports = kwargs['sports'].split(',')
          _sports = [int(x) for x in _sports]
          _sports.sort(reverse=True)
          kwargs['sports'] = ', '.join(six.text_type(x) for x in _sports)
  
          rule += 'sport {{ {0} }} '.format(kwargs['sports'])
          del kwargs['sports']
  
      # Jumps should appear last, except for any arguments that are passed to
      # jumps, which of course need to follow.
      after_jump = []
  
      if 'jump' in kwargs:
          after_jump.append('{0} '.format(kwargs['jump']))
          del kwargs['jump']
  
      if 'j' in kwargs:
          after_jump.append('{0} '.format(kwargs['j']))
          del kwargs['j']
  
      if 'to-port' in kwargs:
          after_jump.append('--to-port {0} '.format(kwargs['to-port']))
          del kwargs['to-port']
  
      if 'to-ports' in kwargs:
          after_jump.append('--to-ports {0} '.format(kwargs['to-ports']))
          del kwargs['to-ports']
  
      if 'to-destination' in kwargs:
          after_jump.append('--to-destination {0} '.format(kwargs['to-destination']))
          del kwargs['to-destination']
  
      if 'reject-with' in kwargs:
          after_jump.append('--reject-with {0} '.format(kwargs['reject-with']))
          del kwargs['reject-with']
  
      for item in after_jump:
          rule += item
  
      # Strip trailing spaces off rule
      rule = rule.strip()
  
      # Insert the protocol prior to dport or sport
      rule = rule.replace('dport', '{0} dport'.format(proto))
      rule = rule.replace('sport', '{0} sport'.format(proto))
  
      ret['rule'] = rule
  
      if full in ['True', 'true']:
  
          if not table:
              ret['comment'] = 'Table needs to be specified'
              return ret
  
          if not chain:
              ret['comment'] = 'Chain needs to be specified'
              return ret
  
          if not command:
              ret['comment'] = 'Command needs to be specified'
              return ret
  
          if command in ['Insert', 'insert', 'INSERT']:
              if position:
                  ret['rule'] = '{0} insert rule {1} {2} {3} ' \
                                'position {4} {5}'.format(_nftables_cmd(),
                                                          nft_family,
                                                          table,
                                                          chain,
                                                          position,
                                                          rule)
              else:
                  ret['rule'] = '{0} insert rule ' \
                                '{1} {2} {3} {4}'.format(_nftables_cmd(),
                                                         nft_family,
                                                         table,
                                                         chain,
                                                         rule)
          else:
              ret['rule'] = '{0} {1} rule {2} {3} {4} {5}'.format(_nftables_cmd(),
                                                                  command,
                                                                  nft_family,
                                                                  table,
                                                                  chain,
                                                                  rule)
  
      if ret['rule']:
          ret['comment'] = 'Successfully built rule'
      ret['result'] = True
      return ret