util.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package autocomplete
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. )
  7. // SanitizeSearch trims whitespace from an autocomplete search string.
  8. func SanitizeSearch(search string) string {
  9. return strings.TrimSpace(search)
  10. }
  11. // NormalizeLimit applies default and maximum limits for autocomplete results.
  12. func NormalizeLimit(limit int) (int, error) {
  13. if limit <= 0 {
  14. return DefaultResultLimit, nil
  15. }
  16. if limit > MaxResultLimit {
  17. return 0, fmt.Errorf("%w: exceeded maximum autocomplete result limit of %d", ErrBadRequest, MaxResultLimit)
  18. }
  19. return limit, nil
  20. }
  21. // MapValueFold returns the value for key using case-insensitive key matching.
  22. func MapValueFold(values map[string]string, key string) (string, bool) {
  23. if v, ok := values[key]; ok {
  24. return v, true
  25. }
  26. for k, v := range values {
  27. if strings.EqualFold(k, key) {
  28. return v, true
  29. }
  30. }
  31. return "", false
  32. }
  33. // UniqueSortedLimited returns sorted unique strings capped at limit.
  34. func UniqueSortedLimited(values map[string]struct{}, limit int) []string {
  35. out := make([]string, 0, len(values))
  36. for v := range values {
  37. out = append(out, v)
  38. }
  39. sort.Strings(out)
  40. if len(out) > limit {
  41. return out[:limit]
  42. }
  43. return out
  44. }
  45. // FilterBySearch returns values from list that contain search (case-insensitive).
  46. func FilterBySearch(list []string, search string) []string {
  47. search = SanitizeSearch(search)
  48. if search == "" {
  49. out := make([]string, len(list))
  50. copy(out, list)
  51. return out
  52. }
  53. needle := strings.ToLower(search)
  54. out := make([]string, 0, len(list))
  55. for _, value := range list {
  56. if strings.Contains(strings.ToLower(value), needle) {
  57. out = append(out, value)
  58. }
  59. }
  60. return out
  61. }
  62. // ToSet converts a string slice to a set map.
  63. func ToSet(values []string) map[string]struct{} {
  64. out := make(map[string]struct{}, len(values))
  65. for _, v := range values {
  66. out[v] = struct{}{}
  67. }
  68. return out
  69. }