ValidateCapabilityIDs reports whether every capability identifier is safe for exact matching.
(values []string, path string)
| 667 | |
| 668 | // ValidateCapabilityIDs reports whether every capability identifier is safe for exact matching. |
| 669 | func ValidateCapabilityIDs(values []string, path string) error { |
| 670 | if strings.TrimSpace(path) == "" { |
| 671 | return fmt.Errorf("%w: capability path is required", ErrValidation) |
| 672 | } |
| 673 | seen := make(map[string]struct{}, len(values)) |
| 674 | for idx, raw := range values { |
| 675 | value := strings.TrimSpace(raw) |
| 676 | field := fmt.Sprintf("%s[%d]", path, idx) |
| 677 | if value == "" { |
| 678 | return fmt.Errorf("%w: %s is required", ErrValidation, field) |
| 679 | } |
| 680 | if len(value) > maxCapabilityIDLength { |
| 681 | return fmt.Errorf("%w: %s exceeds %d bytes", ErrValidation, field, maxCapabilityIDLength) |
| 682 | } |
| 683 | if containsCapabilitySeparator(value) { |
| 684 | return fmt.Errorf("%w: %s must not contain whitespace or commas", ErrValidation, field) |
| 685 | } |
| 686 | if _, ok := seen[value]; ok { |
| 687 | return fmt.Errorf("%w: %s duplicates capability %q", ErrValidation, field, value) |
| 688 | } |
| 689 | seen[value] = struct{}{} |
| 690 | } |
| 691 | return nil |
| 692 | } |
| 693 | |
| 694 | func containsCapabilitySeparator(value string) bool { |
| 695 | return strings.ContainsAny(value, " \t\r\n,") |
no test coverage detected