postmoogle/vendor/go.mau.fi/util/exstrings/stringutil.go
2025-06-24 10:57:16 +03:00

76 lines
2 KiB
Go

// Copyright (c) 2025 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package exstrings
import (
"crypto/sha256"
"crypto/subtle"
"strings"
"unsafe"
)
// UnsafeBytes returns a byte slice that points to the same memory as the input string.
//
// The returned byte slice must not be modified.
func UnsafeBytes(str string) []byte {
return unsafe.Slice(unsafe.StringData(str), len(str))
}
// SHA256 returns the SHA-256 hash of the input string without copying the string.
func SHA256(str string) [32]byte {
return sha256.Sum256(UnsafeBytes(str))
}
// ConstantTimeEqual compares two strings using [subtle.ConstantTimeCompare] without copying the strings.
//
// Note that ConstantTimeCompare is not constant time if the strings are of different length.
func ConstantTimeEqual(a, b string) bool {
return subtle.ConstantTimeCompare(UnsafeBytes(a), UnsafeBytes(b)) == 1
}
// LongestSequenceOf returns the length of the longest contiguous sequence of a single rune in a string.
func LongestSequenceOf(a string, b rune) int {
// IndexRune has some optimizations, so use it to find the starting point
firstIndex := strings.IndexRune(a, b)
if firstIndex == -1 {
return 0
}
count := 0
maxCount := 0
for _, r := range a[firstIndex:] {
if r == b {
count++
if count > maxCount {
maxCount = count
}
} else {
count = 0
}
}
return maxCount
}
// LongestSequenceOfFunc returns the length of the longest contiguous sequence of runes in a string.
//
// If the provided function returns zero or higher, the return value is added to the current count.
// If the return value is negative, the count is reset to zero.
func LongestSequenceOfFunc(a string, fn func(b rune) int) int {
count := 0
maxCount := 0
for _, r := range a {
val := fn(r)
if val < 0 {
count = 0
} else {
count += val
if count > maxCount {
maxCount = count
}
}
}
return maxCount
}