func NewTranslator(from, to string) *Translator {
	tr := &Translator{}
	if from == "" {
		return tr
	}
	reverted := from[0] == '^'
	deletion := len(to) == 0
	if reverted {
		from = from[1:]
	}
	var fromStart, fromEnd, fromRangeStep rune
	var toStart, toEnd, toRangeStep rune
	var fromRangeSize, toRangeSize rune
	var singleRunes []rune
	updateRange := func() {
		if toEnd == utf8.RuneError {
			return
		}
		if toRangeStep == 0 {
			to, toStart, toEnd, toRangeStep = nextRuneRange(to, toEnd)
			return
		}
		if toStart != toEnd {
			toStart += toRangeStep
			return
		}
		if to == "" {
			toEnd = utf8.RuneError
			return
		}
		to, toStart, toEnd, toRangeStep = nextRuneRange(to, utf8.RuneError)
	}
	if deletion {
		toStart = utf8.RuneError
		toEnd = utf8.RuneError
	} else {
		if reverted {
			var size int
			for len(to) > 0 {
				toStart, size = utf8.DecodeRuneInString(to)
				to = to[size:]
			}
			toEnd = utf8.RuneError
		} else {
			to, toStart, toEnd, toRangeStep = nextRuneRange(to, utf8.RuneError)
		}
	}
	fromEnd = utf8.RuneError
	for len(from) > 0 {
		from, fromStart, fromEnd, fromRangeStep = nextRuneRange(from, fromEnd)
		if fromRangeStep == 0 {
			singleRunes = tr.addRune(fromStart, toStart, singleRunes)
			updateRange()
			continue
		}
		for toEnd != utf8.RuneError && fromStart != fromEnd {
			if toRangeStep == 0 {
				singleRunes = tr.addRune(fromStart, toStart, singleRunes)
				updateRange()
				fromStart += fromRangeStep
				continue
			}
			fromRangeSize = (fromEnd - fromStart) * fromRangeStep
			toRangeSize = (toEnd - toStart) * toRangeStep
			if fromRangeSize > toRangeSize {
				fromStart, toStart = tr.addRuneRange(fromStart, fromStart+toRangeSize*fromRangeStep, toStart, toEnd, singleRunes)
				fromStart += fromRangeStep
				updateRange()
				if fromStart == fromEnd {
					singleRunes = tr.addRune(fromStart, toStart, singleRunes)
					updateRange()
				}
				continue
			}
			fromStart, toStart = tr.addRuneRange(fromStart, fromEnd, toStart, toStart+fromRangeSize*toRangeStep, singleRunes)
			updateRange()
			break
		}
		if fromStart == fromEnd {
			fromEnd = utf8.RuneError
			continue
		}
		fromStart, toStart = tr.addRuneRange(fromStart, fromEnd, toStart, toStart, singleRunes)
		fromEnd = utf8.RuneError
	}
	if fromEnd != utf8.RuneError {
		singleRunes = tr.addRune(fromEnd, toStart, singleRunes)
	}
	tr.reverted = reverted
	tr.mappedRune = -1
	tr.hasPattern = true
	if deletion || reverted {
		tr.mappedRune = toStart
	}
	return tr
}
NewTranslator creates new Translator through a from/to pattern pair.
package xstrings
import (
	"bytes"
	"unicode"
	"unicode/utf8"
)
type runeRangeMap struct {
	FromLo rune  
	FromHi rune  
	ToLo   rune
	ToHi   rune
}
type runeDict struct {
	Dict [unicode.MaxASCII + 1]rune
}
type runeMap map[rune]rune
type Translator struct {
	quickDict  *runeDict        
	runeMap    runeMap          
	ranges     []*runeRangeMap  
	mappedRune rune             
	reverted   bool             
	hasPattern bool
}