elvish/pkg/eval/vals/index_string.go

53 lines
1.1 KiB
Go
Raw Normal View History

2018-03-02 07:15:51 +08:00
package vals
2018-03-02 07:59:19 +08:00
import (
"errors"
"unicode/utf8"
)
var errIndexNotAtRuneBoundary = errors.New("index not at rune boundary")
2018-03-02 07:15:51 +08:00
func indexString(s string, index any) (string, error) {
2018-03-02 07:15:51 +08:00
i, j, err := convertStringIndex(index, s)
if err != nil {
return "", err
}
return s[i:j], nil
}
func convertStringIndex(rawIndex any, s string) (int, int, error) {
2018-03-02 07:15:51 +08:00
index, err := ConvertListIndex(rawIndex, len(s))
if err != nil {
return 0, 0, err
}
if index.Slice {
lower, upper := index.Lower, index.Upper
if startsWithRuneBoundary(s[lower:]) && endsWithRuneBoundary(s[:upper]) {
return lower, upper, nil
}
return 0, 0, errIndexNotAtRuneBoundary
}
// Not slice
2018-03-02 07:15:51 +08:00
r, size := utf8.DecodeRuneInString(s[index.Lower:])
if r == utf8.RuneError {
2018-03-02 07:59:19 +08:00
return 0, 0, errIndexNotAtRuneBoundary
2018-03-02 07:15:51 +08:00
}
return index.Lower, index.Lower + size, nil
}
func startsWithRuneBoundary(s string) bool {
if s == "" {
return true
}
r, _ := utf8.DecodeRuneInString(s)
return r != utf8.RuneError
}
func endsWithRuneBoundary(s string) bool {
if s == "" {
return true
}
r, _ := utf8.DecodeLastRuneInString(s)
return r != utf8.RuneError
}