package utils
import (
"fmt"
"regexp"
"time"
)
const (
ShortIDLen = 12 )
const (
MinSampleRate = 1000 MaxSampleRate = 500000 )
const (
MaxNameLen = 140 MaxDatasetNameLen = 255 MaxDescriptionLen = 255 MaxPathLen = 255 MaxFileNameLen = 255 MaxTimezoneLen = 40 )
var shortIDRegex = regexp.MustCompile(`^[A-Za-z0-9_-]{12}$`)
func ValidateShortID(id, fieldName string) error {
if id == "" {
return fmt.Errorf("%s cannot be empty", fieldName)
}
if len(id) != ShortIDLen {
return fmt.Errorf("%s must be exactly %d characters (got %d)", fieldName, ShortIDLen, len(id))
}
if !shortIDRegex.MatchString(id) {
return fmt.Errorf("%s has invalid format (expected alphanumeric nanoid)", fieldName)
}
return nil
}
func ValidateOptionalShortID(id *string, fieldName string) error {
if id == nil || *id == "" {
return nil
}
return ValidateShortID(*id, fieldName)
}
func ValidateStringLength(value, fieldName string, maxLen int) error {
if len(value) > maxLen {
return fmt.Errorf("%s must be %d characters or less (got %d)", fieldName, maxLen, len(value))
}
return nil
}
func ValidateOptionalStringLength(value *string, fieldName string, maxLen int) error {
if value == nil || *value == "" {
return nil
}
return ValidateStringLength(*value, fieldName, maxLen)
}
func ValidateRange[T int | float64](value T, fieldName string, min, max T) error {
if value < min || value > max {
return fmt.Errorf("%s must be between %v and %v (got %v)", fieldName, min, max, value)
}
return nil
}
func ValidatePositive[T int | float64](value T, fieldName string) error {
if value <= 0 {
return fmt.Errorf("%s must be positive (got %v)", fieldName, value)
}
return nil
}
func ValidateNonNegative[T int | float64](value T, fieldName string) error {
if value < 0 {
return fmt.Errorf("%s must be non-negative (got %v)", fieldName, value)
}
return nil
}
func ValidateSampleRate(rate int) error {
return ValidateRange(rate, "sample_rate", MinSampleRate, MaxSampleRate)
}
func ValidateTimezone(tzID string) error {
if _, err := time.LoadLocation(tzID); err != nil {
return fmt.Errorf("invalid timezone_id '%s': %w", tzID, err)
}
return nil
}