func (t *graphemesTrie) lookupValue(n uint32, b byte) property {
	switch {
	default:
		return property(graphemesValues[n<<6+uint32(b)])
	}
}
lookupValue determines the type of block n and looks up the value for b.
package graphemes
type property uint16
const (
	_CR property = 1 << iota
	_Control
	_Extend
	_ExtendedPictographic
	_L
	_LF
	_LV
	_LVT
	_Prepend
	_RegionalIndicator
	_SpacingMark
	_T
	_V
	_ZWJ
)
func (t *graphemesTrie) lookup(s []byte) (v property, sz int) {
	c0 := s[0]
	switch {
	case c0 < 0x80:  
		return graphemesValues[c0], 1
	case c0 < 0xC2:
		return 0, 1  
	case c0 < 0xE0:  
		if len(s) < 2 {
			return 0, 0
		}
		i := graphemesIndex[c0]
		c1 := s[1]
		if c1 < 0x80 || 0xC0 <= c1 {
			return 0, 1  
		}
		return t.lookupValue(uint32(i), c1), 2
	case c0 < 0xF0:  
		if len(s) < 3 {
			return 0, 0
		}
		i := graphemesIndex[c0]
		c1 := s[1]
		if c1 < 0x80 || 0xC0 <= c1 {
			return 0, 1  
		}
		o := uint32(i)<<6 + uint32(c1)
		i = graphemesIndex[o]
		c2 := s[2]
		if c2 < 0x80 || 0xC0 <= c2 {
			return 0, 2  
		}
		return t.lookupValue(uint32(i), c2), 3
	case c0 < 0xF8:  
		if len(s) < 4 {
			return 0, 0
		}
		i := graphemesIndex[c0]
		c1 := s[1]
		if c1 < 0x80 || 0xC0 <= c1 {
			return 0, 1  
		}
		o := uint32(i)<<6 + uint32(c1)
		i = graphemesIndex[o]
		c2 := s[2]
		if c2 < 0x80 || 0xC0 <= c2 {
			return 0, 2  
		}
		o = uint32(i)<<6 + uint32(c2)
		i = graphemesIndex[o]
		c3 := s[3]
		if c3 < 0x80 || 0xC0 <= c3 {
			return 0, 3  
		}
		return t.lookupValue(uint32(i), c3), 4
	}
	return 0, 1
}
type graphemesTrie struct{}
func newGraphemesTrie(i int) *graphemesTrie {
	return &graphemesTrie{}
}