|
- package stringprep
-
- import (
- "golang.org/x/text/unicode/norm"
- )
-
- // Profile represents a stringprep profile.
- type Profile struct {
- Mappings []Mapping
- Normalize bool
- Prohibits []Set
- CheckBiDi bool
- }
-
- var errProhibited = "prohibited character"
-
- // Prepare transforms an input string to an output string following
- // the rules defined in the profile as defined by RFC-3454.
- func (p Profile) Prepare(s string) (string, error) {
- // Optimistically, assume output will be same length as input
- temp := make([]rune, 0, len(s))
-
- // Apply maps
- for _, r := range s {
- rs, ok := p.applyMaps(r)
- if ok {
- temp = append(temp, rs...)
- } else {
- temp = append(temp, r)
- }
- }
-
- // Normalize
- var out string
- if p.Normalize {
- out = norm.NFKC.String(string(temp))
- } else {
- out = string(temp)
- }
-
- // Check prohibited
- for _, r := range out {
- if p.runeIsProhibited(r) {
- return "", Error{Msg: errProhibited, Rune: r}
- }
- }
-
- // Check BiDi allowed
- if p.CheckBiDi {
- if err := passesBiDiRules(out); err != nil {
- return "", err
- }
- }
-
- return out, nil
- }
-
- func (p Profile) applyMaps(r rune) ([]rune, bool) {
- for _, m := range p.Mappings {
- rs, ok := m.Map(r)
- if ok {
- return rs, true
- }
- }
- return nil, false
- }
-
- func (p Profile) runeIsProhibited(r rune) bool {
- for _, s := range p.Prohibits {
- if s.Contains(r) {
- return true
- }
- }
- return false
- }
|