mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 08:32:25 -05:00 
			
		
		
		
	
		
			
	
	
		
			113 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			113 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package split | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"strconv" | ||
|  | 	"time" | ||
|  | 	"unsafe" | ||
|  | 
 | ||
|  | 	"codeberg.org/gruf/go-bytesize" | ||
|  | ) | ||
|  | 
 | ||
|  | // joinFunc will join given slice of elements, using the passed function to append each element at index | ||
|  | // from the slice, forming a combined comma-space separated string. Passed size is for buffer preallocation. | ||
|  | func JoinFunc[T any](slice []T, each func(buf []byte, value T) []byte, size int) string { | ||
|  | 
 | ||
|  | 	// Move nil check | ||
|  | 	// outside main loop. | ||
|  | 	if each == nil { | ||
|  | 		panic("nil func") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Catch easiest case | ||
|  | 	if len(slice) == 0 { | ||
|  | 		return "" | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Preallocate string buffer (size + commas) | ||
|  | 	buf := make([]byte, 0, size+len(slice)-1) | ||
|  | 
 | ||
|  | 	for _, value := range slice { | ||
|  | 		// Append each item | ||
|  | 		buf = each(buf, value) | ||
|  | 		buf = append(buf, ',', ' ') | ||
|  | 	} | ||
|  | 
 | ||
|  | 	// Drop final comma-space | ||
|  | 	buf = buf[:len(buf)-2] | ||
|  | 
 | ||
|  | 	// Directly cast buf to string | ||
|  | 	data := unsafe.SliceData(buf) | ||
|  | 	return unsafe.String(data, len(buf)) | ||
|  | } | ||
|  | 
 | ||
|  | // JoinStrings will pass string slice to JoinFunc(), quoting where | ||
|  | // necessary and combining into a single comma-space separated string. | ||
|  | func JoinStrings[String ~string](slice []String) string { | ||
|  | 	var size int | ||
|  | 	for _, str := range slice { | ||
|  | 		size += len(str) | ||
|  | 	} | ||
|  | 	return JoinFunc(slice, func(buf []byte, value String) []byte { | ||
|  | 		return appendQuote(buf, string(value)) | ||
|  | 	}, size) | ||
|  | } | ||
|  | 
 | ||
|  | // JoinBools will pass bool slice to JoinFunc(), formatting | ||
|  | // and combining into a single comma-space separated string. | ||
|  | func JoinBools[Bool ~bool](slice []Bool) string { | ||
|  | 	return JoinFunc(slice, func(buf []byte, value Bool) []byte { | ||
|  | 		return strconv.AppendBool(buf, bool(value)) | ||
|  | 	}, len(slice)*5 /* len("false") */) | ||
|  | } | ||
|  | 
 | ||
|  | // JoinInts will pass signed integer slice to JoinFunc(), formatting | ||
|  | // and combining into a single comma-space separated string. | ||
|  | func JoinInts[Int Signed](slice []Int) string { | ||
|  | 	return JoinFunc(slice, func(buf []byte, value Int) []byte { | ||
|  | 		return strconv.AppendInt(buf, int64(value), 10) | ||
|  | 	}, len(slice)*20) // max signed int str len | ||
|  | } | ||
|  | 
 | ||
|  | // JoinUints will pass unsigned integer slice to JoinFunc(), | ||
|  | // formatting and combining into a single comma-space separated string. | ||
|  | func JoinUints[Uint Unsigned](slice []Uint) string { | ||
|  | 	return JoinFunc(slice, func(buf []byte, value Uint) []byte { | ||
|  | 		return strconv.AppendUint(buf, uint64(value), 10) | ||
|  | 	}, len(slice)*20) // max unsigned int str len | ||
|  | } | ||
|  | 
 | ||
|  | // JoinFloats will pass float slice to JoinFunc(), formatting | ||
|  | // and combining into a single comma-space separated string. | ||
|  | func JoinFloats[Float_ Float](slice []Float_) string { | ||
|  | 	bits := int(unsafe.Sizeof(Float_(0)) * 8) // param type bits | ||
|  | 	return JoinFunc(slice, func(buf []byte, value Float_) []byte { | ||
|  | 		return strconv.AppendFloat(buf, float64(value), 'g', -1, bits) | ||
|  | 	}, len(slice)*20) // max signed int str len (it's a good guesstimate) | ||
|  | } | ||
|  | 
 | ||
|  | // JoinSizes will pass byte size slice to JoinFunc(), formatting | ||
|  | // and combining into a single comma-space separated string. | ||
|  | func JoinSizes(slice []bytesize.Size) string { | ||
|  | 	const iecLen = 7 // max IEC string length | ||
|  | 	return JoinFunc(slice, func(buf []byte, value bytesize.Size) []byte { | ||
|  | 		return value.AppendFormatIEC(buf) | ||
|  | 	}, len(slice)*iecLen) | ||
|  | } | ||
|  | 
 | ||
|  | // JoinDurations will pass duration slice to JoinFunc(), formatting | ||
|  | // and combining into a single comma-space separated string. | ||
|  | func JoinDurations(slice []time.Duration) string { | ||
|  | 	const durLen = 10 // max duration string length | ||
|  | 	return JoinFunc(slice, func(buf []byte, value time.Duration) []byte { | ||
|  | 		return append(buf, value.String()...) | ||
|  | 	}, len(slice)*durLen) | ||
|  | } | ||
|  | 
 | ||
|  | // JoinTimes will pass time slice to JoinFunc(), formatting | ||
|  | // and combining into a single comma-space separated string. | ||
|  | func JoinTimes(slice []time.Time, format string) string { | ||
|  | 	return JoinFunc(slice, func(buf []byte, value time.Time) []byte { | ||
|  | 		return value.AppendFormat(buf, format) | ||
|  | 	}, len(slice)*len(format)) | ||
|  | } |