feat: add BVK exchange library

This commit is contained in:
Георгий
2026-07-12 20:44:44 +03:00
parent 3a1c524eb2
commit 0ff0905a9c
15 changed files with 627 additions and 0 deletions

88
validation.go Normal file
View File

@@ -0,0 +1,88 @@
package mila
import (
"errors"
"fmt"
"strings"
"unicode/utf8"
)
type Config struct {
MaxRouteLen int
MaxTextLen int
MaxTemplateLen int
}
func DefaultConfig() Config {
return Config{
MaxRouteLen: 3,
MaxTextLen: 200,
MaxTemplateLen: 200,
}
}
type ValidationError struct {
Field string `json:"field"`
Msg string `json:"message"`
}
func (e ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Msg)
}
func Validate(cfg Config, state ContentState) error {
cfg = normalizeConfig(cfg)
state.Route = strings.TrimSpace(state.Route)
state.Template = strings.TrimSpace(state.Template)
if state.Route == "" {
return ValidationError{Field: "route", Msg: "is required"}
}
if runeLen(state.Route) > cfg.MaxRouteLen {
return ValidationError{Field: "route", Msg: fmt.Sprintf("must be at most %d characters", cfg.MaxRouteLen)}
}
if !utf8.ValidString(state.Route) {
return ValidationError{Field: "route", Msg: "must be valid UTF-8"}
}
if !utf8.ValidString(state.Text) {
return ValidationError{Field: "str", Msg: "must be valid UTF-8"}
}
if runeLen(state.Text) > cfg.MaxTextLen {
return ValidationError{Field: "str", Msg: fmt.Sprintf("must be at most %d characters", cfg.MaxTextLen)}
}
if state.Template == "" {
return ValidationError{Field: "tpl_name", Msg: "is required"}
}
if !utf8.ValidString(state.Template) {
return ValidationError{Field: "tpl_name", Msg: "must be valid UTF-8"}
}
if runeLen(state.Template) > cfg.MaxTemplateLen {
return ValidationError{Field: "tpl_name", Msg: fmt.Sprintf("must be at most %d characters", cfg.MaxTemplateLen)}
}
return nil
}
func IsValidationError(err error) bool {
var target ValidationError
return errors.As(err, &target)
}
func normalizeConfig(cfg Config) Config {
def := DefaultConfig()
if cfg.MaxRouteLen <= 0 {
cfg.MaxRouteLen = def.MaxRouteLen
}
if cfg.MaxTextLen <= 0 {
cfg.MaxTextLen = def.MaxTextLen
}
if cfg.MaxTemplateLen <= 0 {
cfg.MaxTemplateLen = def.MaxTemplateLen
}
return cfg
}
func runeLen(s string) int {
return utf8.RuneCountInString(s)
}