letters.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // SPDX-FileCopyrightText: Adam Evyčędo
  2. //
  3. // SPDX-License-Identifier: AGPL-3.0-or-later
  4. package transformers
  5. import (
  6. "unicode"
  7. "unicode/utf8"
  8. "golang.org/x/text/transform"
  9. )
  10. func Replace(f func(r rune) []rune) transform.Transformer {
  11. return replaceF(f)
  12. }
  13. const runeErrorString = string(utf8.RuneError)
  14. type replaceF func(r rune) []rune
  15. func (replaceF) Reset() {}
  16. func (t replaceF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
  17. for nSrc < len(src) {
  18. r, _ := utf8.DecodeRune(src[nSrc:])
  19. if r == utf8.RuneError {
  20. if !atEOF && !utf8.FullRune(src[nSrc:]) {
  21. err = transform.ErrShortSrc
  22. break
  23. }
  24. if nDst+3 > len(dst) {
  25. err = transform.ErrShortDst
  26. break
  27. }
  28. dst[nDst+0] = runeErrorString[0]
  29. dst[nDst+1] = runeErrorString[1]
  30. dst[nDst+2] = runeErrorString[2]
  31. nSrc++
  32. continue
  33. }
  34. replacement := t(r)
  35. size := 0
  36. for _, r2 := range replacement {
  37. r2b := []byte(string(r2))
  38. size += len(r2b)
  39. }
  40. if nDst+size > len(dst) {
  41. err = transform.ErrShortDst
  42. break
  43. }
  44. for _, r2 := range replacement {
  45. r2b := []byte(string(r2))
  46. s := len(r2b)
  47. for i := 0; i < s; i++ {
  48. dst[nDst] = r2b[i]
  49. nDst++
  50. }
  51. nSrc++
  52. }
  53. }
  54. return
  55. }
  56. type Replacer interface {
  57. Replace(r rune) []rune
  58. }
  59. func IsNonAlphanum(r rune) bool {
  60. return !(unicode.IsLetter(r) || unicode.IsDigit(r))
  61. }