func ensureBidirectionalRuneTable(table *map[rune]rune, charsA, charsB string) {
	updateTablesLock.RLock()
	if *table != nil {
		updateTablesLock.RUnlock()
		return
	}
	updateTablesLock.RUnlock()
	updateTablesLock.Lock()
	defer updateTablesLock.Unlock()
	if *table != nil {
		return
	}
	*table = makeBidirectionalRuneTableUnsafe(charsA, charsB)
}
assumes not updated, only ever created once
package transform
import (
	"sync"
	"unicode/utf8"
)
var updateTablesLock sync.RWMutex
func makeBidirectionalRuneTableUnsafe(charsA, charsB string) map[rune]rune {
	if utf8.RuneCountInString(charsA) != utf8.RuneCountInString(charsB) {
		panic("hard error in source mismatched lengths of string replacements")
	}
	table := make(map[rune]rune, 2*len(charsA))
	var ri, rj rune
	for i, j, wi, wj := 0, 0, 0, 0; i < len(charsA); {
		ri, wi = utf8.DecodeRuneInString(charsA[i:])
		rj, wj = utf8.DecodeRuneInString(charsB[j:])
		if ri != ' ' && rj != ' ' {
			table[ri] = rj
			table[rj] = ri
		}
		i += wi
		j += wj
	}
	return table
}