github.com/tomwright/dasel@v1.27.3/parse_selector.go (about)

     1  package dasel
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // ParseSelector parses the given selector string and returns a Selector.
    10  func ParseSelector(selector string) (Selector, error) {
    11  	sel := Selector{
    12  		Raw:        selector,
    13  		Current:    "",
    14  		Remaining:  "",
    15  		Type:       "",
    16  		Property:   "",
    17  		Conditions: make([]Condition, 0),
    18  	}
    19  
    20  	{
    21  		nextSelector, read := ExtractNextSelector(sel.Raw)
    22  		sel.Current = nextSelector
    23  		sel.Remaining = sel.Raw[read:]
    24  	}
    25  
    26  	nextSel := strings.TrimPrefix(sel.Current, ".")
    27  	var err error
    28  
    29  	switch {
    30  	case strings.HasPrefix(nextSel, "(?:") && strings.HasSuffix(nextSel, ")"):
    31  		sel, err = processParseSelectorSearch(nextSel, sel)
    32  	case strings.HasPrefix(nextSel, "(#:") && strings.HasSuffix(nextSel, ")"):
    33  		sel, err = processParseSelectorSearchOptional(nextSel, sel)
    34  	case strings.HasPrefix(nextSel, "(") && strings.HasSuffix(nextSel, ")"):
    35  		sel, err = processParseSelectorDynamic(nextSel, sel)
    36  	case nextSel == "[]":
    37  		sel, err = processParseSelectorNextAvailableIndex(nextSel, sel)
    38  	case nextSel == "[*]":
    39  		sel, err = processParseSelectorIndexAny(nextSel, sel)
    40  	case nextSel == "[#]":
    41  		sel, err = processParseSelectorLength(nextSel, sel)
    42  	case nextSel == "[@]":
    43  		sel, err = processParseSelectorType(nextSel, sel)
    44  	case strings.HasPrefix(nextSel, "[") && strings.HasSuffix(nextSel, "]"):
    45  		sel, err = processParseSelectorIndex(nextSel, sel)
    46  	default:
    47  		sel, err = processParseSelectorProperty(nextSel, sel)
    48  	}
    49  
    50  	return sel, err
    51  }
    52  
    53  func getCondition(parts DynamicSelectorParts) (Condition, error) {
    54  	switch parts.Key {
    55  	case "-", "keyValue":
    56  		switch parts.Comparison {
    57  		case "=":
    58  			return &KeyEqualCondition{
    59  				Value: parts.Value,
    60  			}, nil
    61  		case "!=":
    62  			return &KeyEqualCondition{
    63  				Value: parts.Value,
    64  				Not:   true,
    65  			}, nil
    66  		default:
    67  			return nil, &UnknownComparisonOperatorErr{Operator: parts.Comparison}
    68  		}
    69  	default:
    70  
    71  		switch parts.Comparison {
    72  		case "=":
    73  			return &EqualCondition{
    74  				Key:   parts.Key,
    75  				Value: parts.Value,
    76  			}, nil
    77  		case "!=":
    78  			return &EqualCondition{
    79  				Key:   parts.Key,
    80  				Value: parts.Value,
    81  				Not:   true,
    82  			}, nil
    83  		case ">=":
    84  			return &SortedComparisonCondition{
    85  				Key:   parts.Key,
    86  				Value: parts.Value,
    87  				Equal: true,
    88  				After: true,
    89  			}, nil
    90  		case ">":
    91  			return &SortedComparisonCondition{
    92  				Key:   parts.Key,
    93  				Value: parts.Value,
    94  				After: true,
    95  			}, nil
    96  		case "<=":
    97  			return &SortedComparisonCondition{
    98  				Key:   parts.Key,
    99  				Value: parts.Value,
   100  				Equal: true,
   101  			}, nil
   102  		case "<":
   103  			return &SortedComparisonCondition{
   104  				Key:   parts.Key,
   105  				Value: parts.Value,
   106  			}, nil
   107  		default:
   108  			return nil, &UnknownComparisonOperatorErr{Operator: parts.Comparison}
   109  		}
   110  	}
   111  }
   112  
   113  func processParseSelectorDynamic(selector string, sel Selector) (Selector, error) {
   114  	sel.Type = "DYNAMIC"
   115  	dynamicGroups, err := DynamicSelectorToGroups(selector)
   116  	if err != nil {
   117  		return sel, err
   118  	}
   119  
   120  	for _, g := range dynamicGroups {
   121  		parts := FindDynamicSelectorParts(g)
   122  		cond, err := getCondition(parts)
   123  		if err != nil {
   124  			return sel, err
   125  		}
   126  		if cond != nil {
   127  			sel.Conditions = append(sel.Conditions, cond)
   128  		}
   129  	}
   130  
   131  	return sel, nil
   132  }
   133  
   134  func processParseSelectorSearch(selector string, sel Selector) (Selector, error) {
   135  	sel.Type = "SEARCH"
   136  
   137  	dynamicGroups, err := DynamicSelectorToGroups(selector)
   138  	if err != nil {
   139  		return sel, err
   140  	}
   141  	if len(dynamicGroups) != 1 {
   142  		return sel, fmt.Errorf("require exactly 1 group in search selector")
   143  	}
   144  
   145  	for _, g := range dynamicGroups {
   146  		parts := FindDynamicSelectorParts(g)
   147  		parts.Key = strings.TrimPrefix(parts.Key, "?:")
   148  		cond, err := getCondition(parts)
   149  		if err != nil {
   150  			return sel, err
   151  		}
   152  		if cond != nil {
   153  			sel.Conditions = append(sel.Conditions, cond)
   154  		}
   155  	}
   156  
   157  	return sel, nil
   158  }
   159  
   160  func processParseSelectorSearchOptional(selector string, sel Selector) (Selector, error) {
   161  	sel.Type = "SEARCH_OPTIONAL"
   162  
   163  	dynamicGroups, err := DynamicSelectorToGroups(selector)
   164  	if err != nil {
   165  		return sel, err
   166  	}
   167  
   168  	for _, g := range dynamicGroups {
   169  		parts := FindDynamicSelectorParts(g)
   170  		parts.Key = strings.TrimPrefix(parts.Key, "#:")
   171  		cond, err := getCondition(parts)
   172  		if err != nil {
   173  			return sel, err
   174  		}
   175  		if cond != nil {
   176  			sel.Conditions = append(sel.Conditions, cond)
   177  		}
   178  	}
   179  
   180  	return sel, nil
   181  }
   182  
   183  func processParseSelectorNextAvailableIndex(selector string, sel Selector) (Selector, error) {
   184  	sel.Type = "NEXT_AVAILABLE_INDEX"
   185  	return sel, nil
   186  }
   187  
   188  func processParseSelectorIndexAny(selector string, sel Selector) (Selector, error) {
   189  	sel.Type = "INDEX_ANY"
   190  	return sel, nil
   191  }
   192  
   193  func processParseSelectorLength(selector string, sel Selector) (Selector, error) {
   194  	sel.Type = "LENGTH"
   195  	return sel, nil
   196  }
   197  
   198  func processParseSelectorType(selector string, sel Selector) (Selector, error) {
   199  	sel.Type = "TYPE"
   200  	return sel, nil
   201  }
   202  
   203  func processParseSelectorIndex(selector string, sel Selector) (Selector, error) {
   204  	sel.Type = "INDEX"
   205  	indexStr := selector[1 : len(selector)-1]
   206  	index, err := strconv.ParseInt(indexStr, 10, 32)
   207  	if err != nil {
   208  		return sel, &InvalidIndexErr{Index: indexStr}
   209  	}
   210  	sel.Index = int(index)
   211  	return sel, nil
   212  }
   213  
   214  func processParseSelectorProperty(selector string, sel Selector) (Selector, error) {
   215  	sel.Type = "PROPERTY"
   216  	sel.Property = selector
   217  	return sel, nil
   218  }