feat(internal): add ListOr[T any] type

This is a utility type that lets you decode a JSON T or list of T as a
single value. This will be used with Redis Sentinel config so that you
can specify multiple sentinel addresses.

Ref TecharoHQ/botstopper#24

Assisted-by: GLM 4.6 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso
2025-11-18 08:39:30 -05:00
parent 69e9023cbb
commit 7a516580ff
2 changed files with 118 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
package internal
import (
"encoding/json"
)
// ListOr[T any] is a slice that can contain either a single T or multiple T values.
// During JSON unmarshaling, it checks if the first character is '[' to determine
// whether to treat the JSON as an array or a single value.
type ListOr[T any] []T
func (lo *ListOr[T]) UnmarshalJSON(data []byte) error {
if len(data) == 0 {
return nil
}
// Check if first non-whitespace character is '['
firstChar := data[0]
for i := 0; i < len(data); i++ {
if data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' {
firstChar = data[i]
break
}
}
if firstChar == '[' {
// It's an array, unmarshal directly
return json.Unmarshal(data, (*[]T)(lo))
} else {
// It's a single value, unmarshal as a single item in a slice
var single T
if err := json.Unmarshal(data, &single); err != nil {
return err
}
*lo = ListOr[T]{single}
}
return nil
}