this repo has no description
at master 121 lines 3.7 kB view raw
1// Copyright 2018 The CUE Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Package strings implements simple functions to manipulate UTF-8 encoded 16// strings.package strings. 17// 18// Some of the functions in this package are specifically intended as field 19// constraints. For instance, MaxRunes as used in this CUE program 20// 21// import "strings" 22// 23// myString: strings.MaxRunes(5) 24// 25// specifies that the myString should be at most 5 code points. 26package strings 27 28import ( 29 "fmt" 30 "strings" 31 "unicode" 32 "unicode/utf8" 33) 34 35// ByteAt reports the ith byte of the underlying strings or byte. 36func ByteAt(b []byte, i int) (byte, error) { 37 if i < 0 || i >= len(b) { 38 return 0, fmt.Errorf("index out of range") 39 } 40 return b[i], nil 41} 42 43// ByteSlice reports the bytes of the underlying string data from the start 44// index up to but not including the end index. 45func ByteSlice(b []byte, start, end int) ([]byte, error) { 46 if start < 0 || start > end || end > len(b) { 47 return nil, fmt.Errorf("index out of range") 48 } 49 return b[start:end], nil 50} 51 52// Runes returns the Unicode code points of the given string. 53func Runes(s string) []rune { 54 return []rune(s) 55} 56 57// MinRunes reports whether the number of runes (Unicode codepoints) in a string 58// is at least a certain minimum. MinRunes can be used a field constraint to 59// except all strings for which this property holds. 60func MinRunes(s string, min int) bool { 61 // TODO: CUE strings cannot be invalid UTF-8. In case this changes, we need 62 // to use the following conversion to count properly: 63 // s, _ = unicodeenc.UTF8.NewDecoder().String(s) 64 return utf8.RuneCountInString(s) >= min 65} 66 67// MaxRunes reports whether the number of runes (Unicode codepoints) in a string 68// exceeds a certain maximum. MaxRunes can be used a field constraint to 69// except all strings for which this property holds 70func MaxRunes(s string, max int) bool { 71 // See comment in MinRunes implementation. 72 return utf8.RuneCountInString(s) <= max 73} 74 75// ToTitle returns a copy of the string s with all Unicode letters that begin 76// words mapped to their title case. 77func ToTitle(s string) string { 78 // Use a closure here to remember state. 79 // Hackish but effective. Depends on Map scanning in order and calling 80 // the closure once per rune. 81 prev := ' ' 82 return strings.Map( 83 func(r rune) rune { 84 if unicode.IsSpace(prev) { 85 prev = r 86 return unicode.ToTitle(r) 87 } 88 prev = r 89 return r 90 }, 91 s) 92} 93 94// ToCamel returns a copy of the string s with all Unicode letters that begin 95// words mapped to lower case. 96func ToCamel(s string) string { 97 // Use a closure here to remember state. 98 // Hackish but effective. Depends on Map scanning in order and calling 99 // the closure once per rune. 100 prev := ' ' 101 return strings.Map( 102 func(r rune) rune { 103 if unicode.IsSpace(prev) { 104 prev = r 105 return unicode.ToLower(r) 106 } 107 prev = r 108 return r 109 }, 110 s) 111} 112 113// SliceRunes returns a string of the underlying string data from the start index 114// up to but not including the end index. 115func SliceRunes(s string, start, end int) (string, error) { 116 runes := []rune(s) 117 if start < 0 || start > end || end > len(runes) { 118 return "", fmt.Errorf("index out of range") 119 } 120 return string(runes[start:end]), nil 121}