mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 08:52:25 -05:00 
			
		
		
		
	
		
			
	
	
		
			262 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			262 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package bytes | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"bytes" | ||
|  | 	"reflect" | ||
|  | 	"unsafe" | ||
|  | ) | ||
|  | 
 | ||
|  | var ( | ||
|  | 	_ Bytes = &Buffer{} | ||
|  | 	_ Bytes = bytesType{} | ||
|  | ) | ||
|  | 
 | ||
|  | // Bytes defines a standard way of retrieving the content of a | ||
|  | // byte buffer of some-kind. | ||
|  | type Bytes interface { | ||
|  | 	// Bytes returns the byte slice content | ||
|  | 	Bytes() []byte | ||
|  | 
 | ||
|  | 	// String returns byte slice cast directly to string, this | ||
|  | 	// will cause an allocation but comes with the safety of | ||
|  | 	// being an immutable Go string | ||
|  | 	String() string | ||
|  | 
 | ||
|  | 	// StringPtr returns byte slice cast to string via the unsafe | ||
|  | 	// package. This comes with the same caveats of accessing via | ||
|  | 	// .Bytes() in that the content is liable change and is NOT | ||
|  | 	// immutable, despite being a string type | ||
|  | 	StringPtr() string | ||
|  | } | ||
|  | 
 | ||
|  | type bytesType []byte | ||
|  | 
 | ||
|  | func (b bytesType) Bytes() []byte { | ||
|  | 	return b | ||
|  | } | ||
|  | 
 | ||
|  | func (b bytesType) String() string { | ||
|  | 	return string(b) | ||
|  | } | ||
|  | 
 | ||
|  | func (b bytesType) StringPtr() string { | ||
|  | 	return BytesToString(b) | ||
|  | } | ||
|  | 
 | ||
|  | // ToBytes casts the provided byte slice as the simplest possible | ||
|  | // Bytes interface implementation | ||
|  | func ToBytes(b []byte) Bytes { | ||
|  | 	return bytesType(b) | ||
|  | } | ||
|  | 
 | ||
|  | // Copy returns a new copy of slice b, does NOT maintain nil values | ||
|  | func Copy(b []byte) []byte { | ||
|  | 	p := make([]byte, len(b)) | ||
|  | 	copy(p, b) | ||
|  | 	return p | ||
|  | } | ||
|  | 
 | ||
|  | // BytesToString returns byte slice cast to string via the "unsafe" package | ||
|  | func BytesToString(b []byte) string { | ||
|  | 	return *(*string)(unsafe.Pointer(&b)) | ||
|  | } | ||
|  | 
 | ||
|  | // StringToBytes returns the string cast to string via the "unsafe" and "reflect" packages | ||
|  | func StringToBytes(s string) []byte { | ||
|  | 	// thank you to https://github.com/valyala/fasthttp/blob/master/bytesconv.go | ||
|  | 	var b []byte | ||
|  | 
 | ||
|  | 	// Get byte + string headers | ||
|  | 	bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) | ||
|  | 	sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) | ||
|  | 
 | ||
|  | 	// Manually set bytes to string | ||
|  | 	bh.Data = sh.Data | ||
|  | 	bh.Len = sh.Len | ||
|  | 	bh.Cap = sh.Len | ||
|  | 
 | ||
|  | 	return b | ||
|  | } | ||
|  | 
 | ||
|  | // // InsertByte inserts the supplied byte into the slice at provided position | ||
|  | // func InsertByte(b []byte, at int, c byte) []byte { | ||
|  | // 	return append(append(b[:at], c), b[at:]...) | ||
|  | // } | ||
|  | 
 | ||
|  | // // Insert inserts the supplied byte slice into the slice at provided position | ||
|  | // func Insert(b []byte, at int, s []byte) []byte { | ||
|  | // 	return append(append(b[:at], s...), b[at:]...) | ||
|  | // } | ||
|  | 
 | ||
|  | // ToUpper offers a faster ToUpper implementation using a lookup table | ||
|  | func ToUpper(b []byte) { | ||
|  | 	for i := 0; i < len(b); i++ { | ||
|  | 		c := &b[i] | ||
|  | 		*c = toUpperTable[*c] | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // ToLower offers a faster ToLower implementation using a lookup table | ||
|  | func ToLower(b []byte) { | ||
|  | 	for i := 0; i < len(b); i++ { | ||
|  | 		c := &b[i] | ||
|  | 		*c = toLowerTable[*c] | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // HasBytePrefix returns whether b has the provided byte prefix | ||
|  | func HasBytePrefix(b []byte, c byte) bool { | ||
|  | 	return (len(b) > 0) && (b[0] == c) | ||
|  | } | ||
|  | 
 | ||
|  | // HasByteSuffix returns whether b has the provided byte suffix | ||
|  | func HasByteSuffix(b []byte, c byte) bool { | ||
|  | 	return (len(b) > 0) && (b[len(b)-1] == c) | ||
|  | } | ||
|  | 
 | ||
|  | // HasBytePrefix returns b without the provided leading byte | ||
|  | func TrimBytePrefix(b []byte, c byte) []byte { | ||
|  | 	if HasBytePrefix(b, c) { | ||
|  | 		return b[1:] | ||
|  | 	} | ||
|  | 	return b | ||
|  | } | ||
|  | 
 | ||
|  | // TrimByteSuffix returns b without the provided trailing byte | ||
|  | func TrimByteSuffix(b []byte, c byte) []byte { | ||
|  | 	if HasByteSuffix(b, c) { | ||
|  | 		return b[:len(b)-1] | ||
|  | 	} | ||
|  | 	return b | ||
|  | } | ||
|  | 
 | ||
|  | // Compare is a direct call-through to standard library bytes.Compare() | ||
|  | func Compare(b, s []byte) int { | ||
|  | 	return bytes.Compare(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // Contains is a direct call-through to standard library bytes.Contains() | ||
|  | func Contains(b, s []byte) bool { | ||
|  | 	return bytes.Contains(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // TrimPrefix is a direct call-through to standard library bytes.TrimPrefix() | ||
|  | func TrimPrefix(b, s []byte) []byte { | ||
|  | 	return bytes.TrimPrefix(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // TrimSuffix is a direct call-through to standard library bytes.TrimSuffix() | ||
|  | func TrimSuffix(b, s []byte) []byte { | ||
|  | 	return bytes.TrimSuffix(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // Equal is a direct call-through to standard library bytes.Equal() | ||
|  | func Equal(b, s []byte) bool { | ||
|  | 	return bytes.Equal(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // EqualFold is a direct call-through to standard library bytes.EqualFold() | ||
|  | func EqualFold(b, s []byte) bool { | ||
|  | 	return bytes.EqualFold(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // Fields is a direct call-through to standard library bytes.Fields() | ||
|  | func Fields(b []byte) [][]byte { | ||
|  | 	return bytes.Fields(b) | ||
|  | } | ||
|  | 
 | ||
|  | // FieldsFunc is a direct call-through to standard library bytes.FieldsFunc() | ||
|  | func FieldsFunc(b []byte, fn func(rune) bool) [][]byte { | ||
|  | 	return bytes.FieldsFunc(b, fn) | ||
|  | } | ||
|  | 
 | ||
|  | // HasPrefix is a direct call-through to standard library bytes.HasPrefix() | ||
|  | func HasPrefix(b, s []byte) bool { | ||
|  | 	return bytes.HasPrefix(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // HasSuffix is a direct call-through to standard library bytes.HasSuffix() | ||
|  | func HasSuffix(b, s []byte) bool { | ||
|  | 	return bytes.HasSuffix(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // Index is a direct call-through to standard library bytes.Index() | ||
|  | func Index(b, s []byte) int { | ||
|  | 	return bytes.Index(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // IndexByte is a direct call-through to standard library bytes.IndexByte() | ||
|  | func IndexByte(b []byte, c byte) int { | ||
|  | 	return bytes.IndexByte(b, c) | ||
|  | } | ||
|  | 
 | ||
|  | // IndexAny is a direct call-through to standard library bytes.IndexAny() | ||
|  | func IndexAny(b []byte, s string) int { | ||
|  | 	return bytes.IndexAny(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // IndexRune is a direct call-through to standard library bytes.IndexRune() | ||
|  | func IndexRune(b []byte, r rune) int { | ||
|  | 	return bytes.IndexRune(b, r) | ||
|  | } | ||
|  | 
 | ||
|  | // IndexFunc is a direct call-through to standard library bytes.IndexFunc() | ||
|  | func IndexFunc(b []byte, fn func(rune) bool) int { | ||
|  | 	return bytes.IndexFunc(b, fn) | ||
|  | } | ||
|  | 
 | ||
|  | // LastIndex is a direct call-through to standard library bytes.LastIndex() | ||
|  | func LastIndex(b, s []byte) int { | ||
|  | 	return bytes.LastIndex(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // LastIndexByte is a direct call-through to standard library bytes.LastIndexByte() | ||
|  | func LastIndexByte(b []byte, c byte) int { | ||
|  | 	return bytes.LastIndexByte(b, c) | ||
|  | } | ||
|  | 
 | ||
|  | // LastIndexAny is a direct call-through to standard library bytes.LastIndexAny() | ||
|  | func LastIndexAny(b []byte, s string) int { | ||
|  | 	return bytes.LastIndexAny(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // LastIndexFunc is a direct call-through to standard library bytes.LastIndexFunc() | ||
|  | func LastIndexFunc(b []byte, fn func(rune) bool) int { | ||
|  | 	return bytes.LastIndexFunc(b, fn) | ||
|  | } | ||
|  | 
 | ||
|  | // Replace is a direct call-through to standard library bytes.Replace() | ||
|  | func Replace(b, s, r []byte, c int) []byte { | ||
|  | 	return bytes.Replace(b, s, r, c) | ||
|  | } | ||
|  | 
 | ||
|  | // ReplaceAll is a direct call-through to standard library bytes.ReplaceAll() | ||
|  | func ReplaceAll(b, s, r []byte) []byte { | ||
|  | 	return bytes.ReplaceAll(b, s, r) | ||
|  | } | ||
|  | 
 | ||
|  | // Split is a direct call-through to standard library bytes.Split() | ||
|  | func Split(b, s []byte) [][]byte { | ||
|  | 	return bytes.Split(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // SplitAfter is a direct call-through to standard library bytes.SplitAfter() | ||
|  | func SplitAfter(b, s []byte) [][]byte { | ||
|  | 	return bytes.SplitAfter(b, s) | ||
|  | } | ||
|  | 
 | ||
|  | // SplitN is a direct call-through to standard library bytes.SplitN() | ||
|  | func SplitN(b, s []byte, c int) [][]byte { | ||
|  | 	return bytes.SplitN(b, s, c) | ||
|  | } | ||
|  | 
 | ||
|  | // SplitAfterN is a direct call-through to standard library bytes.SplitAfterN() | ||
|  | func SplitAfterN(b, s []byte, c int) [][]byte { | ||
|  | 	return bytes.SplitAfterN(b, s, c) | ||
|  | } | ||
|  | 
 | ||
|  | // NewReader is a direct call-through to standard library bytes.NewReader() | ||
|  | func NewReader(b []byte) *bytes.Reader { | ||
|  | 	return bytes.NewReader(b) | ||
|  | } |