code: func ParsePermissions(s string) (*Permissions, error) {
  	ps := &Permissions{}
  
  	if s == "" {
  		return &Permissions{}, nil
  	}
  
  	perms := strings.Split(s, " ")
  
  	for _, perm := range perms {
  		parts := strings.Split(perm, ":")
  
  		switch len(parts) {
  		case 3:
  			actions, err := ParseStringSet(parts[0])
  
  			if err != nil {
  				return nil, fmt.Errorf("action list must look like connect,bind given: %s", parts[0])
  			}
  
  			hosts, err := ParseStringSet(parts[1])
  
  			if err != nil {
  				return nil, fmt.Errorf("hosts list must look like google.pl,*.google.com given: %s", parts[1])
  			}
  
  			ports, err := ParsePortSet(parts[2])
  
  			if err != nil {
  				return nil, fmt.Errorf("ports list must look like 80,8000-9000, given: %s", parts[2])
  			}
  
  			permission := Permission{Actions: *actions, Hosts: *hosts, Ports: *ports}
  
  			*ps = append(*ps, permission)
  		default:
  			return nil, fmt.Errorf("permission must have format [actions]:[hosts]:[ports] given: %s", perm)
  		}
  	}
  
  	return ps, nil
  }
docs: // ParsePermissions parses the s to a Permissions.