bytes.go (7037B)
1 package bytes 2 3 import ( 4 "bytes" 5 "reflect" 6 "unsafe" 7 ) 8 9 var ( 10 _ Bytes = &Buffer{} 11 _ Bytes = bytesType{} 12 ) 13 14 // Bytes defines a standard way of retrieving the content of a 15 // byte buffer of some-kind. 16 type Bytes interface { 17 // Bytes returns the byte slice content 18 Bytes() []byte 19 20 // String returns byte slice cast directly to string, this 21 // will cause an allocation but comes with the safety of 22 // being an immutable Go string 23 String() string 24 25 // StringPtr returns byte slice cast to string via the unsafe 26 // package. This comes with the same caveats of accessing via 27 // .Bytes() in that the content is liable change and is NOT 28 // immutable, despite being a string type 29 StringPtr() string 30 } 31 32 type bytesType []byte 33 34 func (b bytesType) Bytes() []byte { 35 return b 36 } 37 38 func (b bytesType) String() string { 39 return string(b) 40 } 41 42 func (b bytesType) StringPtr() string { 43 return BytesToString(b) 44 } 45 46 // ToBytes casts the provided byte slice as the simplest possible 47 // Bytes interface implementation 48 func ToBytes(b []byte) Bytes { 49 return bytesType(b) 50 } 51 52 // Copy returns a new copy of slice b, does NOT maintain nil values 53 func Copy(b []byte) []byte { 54 p := make([]byte, len(b)) 55 copy(p, b) 56 return p 57 } 58 59 // BytesToString returns byte slice cast to string via the "unsafe" package 60 func BytesToString(b []byte) string { 61 return *(*string)(unsafe.Pointer(&b)) 62 } 63 64 // StringToBytes returns the string cast to string via the "unsafe" and "reflect" packages 65 func StringToBytes(s string) []byte { 66 // thank you to https://github.com/valyala/fasthttp/blob/master/bytesconv.go 67 var b []byte 68 69 // Get byte + string headers 70 bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 71 sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 72 73 // Manually set bytes to string 74 bh.Data = sh.Data 75 bh.Len = sh.Len 76 bh.Cap = sh.Len 77 78 return b 79 } 80 81 // // InsertByte inserts the supplied byte into the slice at provided position 82 // func InsertByte(b []byte, at int, c byte) []byte { 83 // return append(append(b[:at], c), b[at:]...) 84 // } 85 86 // // Insert inserts the supplied byte slice into the slice at provided position 87 // func Insert(b []byte, at int, s []byte) []byte { 88 // return append(append(b[:at], s...), b[at:]...) 89 // } 90 91 // ToUpper offers a faster ToUpper implementation using a lookup table 92 func ToUpper(b []byte) { 93 for i := 0; i < len(b); i++ { 94 c := &b[i] 95 *c = toUpperTable[*c] 96 } 97 } 98 99 // ToLower offers a faster ToLower implementation using a lookup table 100 func ToLower(b []byte) { 101 for i := 0; i < len(b); i++ { 102 c := &b[i] 103 *c = toLowerTable[*c] 104 } 105 } 106 107 // HasBytePrefix returns whether b has the provided byte prefix 108 func HasBytePrefix(b []byte, c byte) bool { 109 return (len(b) > 0) && (b[0] == c) 110 } 111 112 // HasByteSuffix returns whether b has the provided byte suffix 113 func HasByteSuffix(b []byte, c byte) bool { 114 return (len(b) > 0) && (b[len(b)-1] == c) 115 } 116 117 // HasBytePrefix returns b without the provided leading byte 118 func TrimBytePrefix(b []byte, c byte) []byte { 119 if HasBytePrefix(b, c) { 120 return b[1:] 121 } 122 return b 123 } 124 125 // TrimByteSuffix returns b without the provided trailing byte 126 func TrimByteSuffix(b []byte, c byte) []byte { 127 if HasByteSuffix(b, c) { 128 return b[:len(b)-1] 129 } 130 return b 131 } 132 133 // Compare is a direct call-through to standard library bytes.Compare() 134 func Compare(b, s []byte) int { 135 return bytes.Compare(b, s) 136 } 137 138 // Contains is a direct call-through to standard library bytes.Contains() 139 func Contains(b, s []byte) bool { 140 return bytes.Contains(b, s) 141 } 142 143 // TrimPrefix is a direct call-through to standard library bytes.TrimPrefix() 144 func TrimPrefix(b, s []byte) []byte { 145 return bytes.TrimPrefix(b, s) 146 } 147 148 // TrimSuffix is a direct call-through to standard library bytes.TrimSuffix() 149 func TrimSuffix(b, s []byte) []byte { 150 return bytes.TrimSuffix(b, s) 151 } 152 153 // Equal is a direct call-through to standard library bytes.Equal() 154 func Equal(b, s []byte) bool { 155 return bytes.Equal(b, s) 156 } 157 158 // EqualFold is a direct call-through to standard library bytes.EqualFold() 159 func EqualFold(b, s []byte) bool { 160 return bytes.EqualFold(b, s) 161 } 162 163 // Fields is a direct call-through to standard library bytes.Fields() 164 func Fields(b []byte) [][]byte { 165 return bytes.Fields(b) 166 } 167 168 // FieldsFunc is a direct call-through to standard library bytes.FieldsFunc() 169 func FieldsFunc(b []byte, fn func(rune) bool) [][]byte { 170 return bytes.FieldsFunc(b, fn) 171 } 172 173 // HasPrefix is a direct call-through to standard library bytes.HasPrefix() 174 func HasPrefix(b, s []byte) bool { 175 return bytes.HasPrefix(b, s) 176 } 177 178 // HasSuffix is a direct call-through to standard library bytes.HasSuffix() 179 func HasSuffix(b, s []byte) bool { 180 return bytes.HasSuffix(b, s) 181 } 182 183 // Index is a direct call-through to standard library bytes.Index() 184 func Index(b, s []byte) int { 185 return bytes.Index(b, s) 186 } 187 188 // IndexByte is a direct call-through to standard library bytes.IndexByte() 189 func IndexByte(b []byte, c byte) int { 190 return bytes.IndexByte(b, c) 191 } 192 193 // IndexAny is a direct call-through to standard library bytes.IndexAny() 194 func IndexAny(b []byte, s string) int { 195 return bytes.IndexAny(b, s) 196 } 197 198 // IndexRune is a direct call-through to standard library bytes.IndexRune() 199 func IndexRune(b []byte, r rune) int { 200 return bytes.IndexRune(b, r) 201 } 202 203 // IndexFunc is a direct call-through to standard library bytes.IndexFunc() 204 func IndexFunc(b []byte, fn func(rune) bool) int { 205 return bytes.IndexFunc(b, fn) 206 } 207 208 // LastIndex is a direct call-through to standard library bytes.LastIndex() 209 func LastIndex(b, s []byte) int { 210 return bytes.LastIndex(b, s) 211 } 212 213 // LastIndexByte is a direct call-through to standard library bytes.LastIndexByte() 214 func LastIndexByte(b []byte, c byte) int { 215 return bytes.LastIndexByte(b, c) 216 } 217 218 // LastIndexAny is a direct call-through to standard library bytes.LastIndexAny() 219 func LastIndexAny(b []byte, s string) int { 220 return bytes.LastIndexAny(b, s) 221 } 222 223 // LastIndexFunc is a direct call-through to standard library bytes.LastIndexFunc() 224 func LastIndexFunc(b []byte, fn func(rune) bool) int { 225 return bytes.LastIndexFunc(b, fn) 226 } 227 228 // Replace is a direct call-through to standard library bytes.Replace() 229 func Replace(b, s, r []byte, c int) []byte { 230 return bytes.Replace(b, s, r, c) 231 } 232 233 // ReplaceAll is a direct call-through to standard library bytes.ReplaceAll() 234 func ReplaceAll(b, s, r []byte) []byte { 235 return bytes.ReplaceAll(b, s, r) 236 } 237 238 // Split is a direct call-through to standard library bytes.Split() 239 func Split(b, s []byte) [][]byte { 240 return bytes.Split(b, s) 241 } 242 243 // SplitAfter is a direct call-through to standard library bytes.SplitAfter() 244 func SplitAfter(b, s []byte) [][]byte { 245 return bytes.SplitAfter(b, s) 246 } 247 248 // SplitN is a direct call-through to standard library bytes.SplitN() 249 func SplitN(b, s []byte, c int) [][]byte { 250 return bytes.SplitN(b, s, c) 251 } 252 253 // SplitAfterN is a direct call-through to standard library bytes.SplitAfterN() 254 func SplitAfterN(b, s []byte, c int) [][]byte { 255 return bytes.SplitAfterN(b, s, c) 256 } 257 258 // NewReader is a direct call-through to standard library bytes.NewReader() 259 func NewReader(b []byte) *bytes.Reader { 260 return bytes.NewReader(b) 261 }