// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bidi

import 

// Properties provides access to BiDi properties of runes.
type Properties struct {
	entry uint8
	last  uint8
}

var trie = newBidiTrie(0)

// TODO: using this for bidirule reduces the running time by about 5%. Consider
// if this is worth exposing or if we can find a way to speed up the Class
// method.
//
// // CompactClass is like Class, but maps all of the BiDi control classes
// // (LRO, RLO, LRE, RLE, PDF, LRI, RLI, FSI, PDI) to the class Control.
// func (p Properties) CompactClass() Class {
// 	return Class(p.entry & 0x0F)
// }

// Class returns the Bidi class for p.
func ( Properties) () Class {
	 := Class(.entry & 0x0F)
	if  == Control {
		 = controlByteToClass[.last&0xF]
	}
	return 
}

// IsBracket reports whether the rune is a bracket.
func ( Properties) () bool { return .entry&0xF0 != 0 }

// IsOpeningBracket reports whether the rune is an opening bracket.
// IsBracket must return true.
func ( Properties) () bool { return .entry&openMask != 0 }

// TODO: find a better API and expose.
func ( Properties) ( rune) rune {
	return xorMasks[.entry>>xorMaskShift] ^ 
}

var controlByteToClass = [16]Class{
	0xD: LRO, // U+202D LeftToRightOverride,
	0xE: RLO, // U+202E RightToLeftOverride,
	0xA: LRE, // U+202A LeftToRightEmbedding,
	0xB: RLE, // U+202B RightToLeftEmbedding,
	0xC: PDF, // U+202C PopDirectionalFormat,
	0x6: LRI, // U+2066 LeftToRightIsolate,
	0x7: RLI, // U+2067 RightToLeftIsolate,
	0x8: FSI, // U+2068 FirstStrongIsolate,
	0x9: PDI, // U+2069 PopDirectionalIsolate,
}

// LookupRune returns properties for r.
func ( rune) ( Properties,  int) {
	var  [4]byte
	 := utf8.EncodeRune([:], )
	return Lookup([:])
}

// TODO: these lookup methods are based on the generated trie code. The returned
// sizes have slightly different semantics from the generated code, in that it
// always returns size==1 for an illegal UTF-8 byte (instead of the length
// of the maximum invalid subsequence). Most Transformers, like unicode/norm,
// leave invalid UTF-8 untouched, in which case it has performance benefits to
// do so (without changing the semantics). Bidi requires the semantics used here
// for the bidirule implementation to be compatible with the Go semantics.
//  They ultimately should perhaps be adopted by all trie implementations, for
// convenience sake.
// This unrolled code also boosts performance of the secure/bidirule package by
// about 30%.
// So, to remove this code:
//   - add option to trie generator to define return type.
//   - always return 1 byte size for ill-formed UTF-8 runes.

// Lookup returns properties for the first rune in s and the width in bytes of
// its encoding. The size will be 0 if s does not hold enough bytes to complete
// the encoding.
func ( []byte) ( Properties,  int) {
	 := [0]
	switch {
	case  < 0x80: // is ASCII
		return Properties{entry: bidiValues[]}, 1
	case  < 0xC2:
		return Properties{}, 1
	case  < 0xE0: // 2-byte UTF-8
		if len() < 2 {
			return Properties{}, 0
		}
		 := bidiIndex[]
		 := [1]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		return Properties{entry: trie.lookupValue(uint32(), )}, 2
	case  < 0xF0: // 3-byte UTF-8
		if len() < 3 {
			return Properties{}, 0
		}
		 := bidiIndex[]
		 := [1]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		 := uint32()<<6 + uint32()
		 = bidiIndex[]
		 := [2]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		return Properties{entry: trie.lookupValue(uint32(), ), last: }, 3
	case  < 0xF8: // 4-byte UTF-8
		if len() < 4 {
			return Properties{}, 0
		}
		 := bidiIndex[]
		 := [1]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		 := uint32()<<6 + uint32()
		 = bidiIndex[]
		 := [2]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		 = uint32()<<6 + uint32()
		 = bidiIndex[]
		 := [3]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		return Properties{entry: trie.lookupValue(uint32(), )}, 4
	}
	// Illegal rune
	return Properties{}, 1
}

// LookupString returns properties for the first rune in s and the width in
// bytes of its encoding. The size will be 0 if s does not hold enough bytes to
// complete the encoding.
func ( string) ( Properties,  int) {
	 := [0]
	switch {
	case  < 0x80: // is ASCII
		return Properties{entry: bidiValues[]}, 1
	case  < 0xC2:
		return Properties{}, 1
	case  < 0xE0: // 2-byte UTF-8
		if len() < 2 {
			return Properties{}, 0
		}
		 := bidiIndex[]
		 := [1]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		return Properties{entry: trie.lookupValue(uint32(), )}, 2
	case  < 0xF0: // 3-byte UTF-8
		if len() < 3 {
			return Properties{}, 0
		}
		 := bidiIndex[]
		 := [1]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		 := uint32()<<6 + uint32()
		 = bidiIndex[]
		 := [2]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		return Properties{entry: trie.lookupValue(uint32(), ), last: }, 3
	case  < 0xF8: // 4-byte UTF-8
		if len() < 4 {
			return Properties{}, 0
		}
		 := bidiIndex[]
		 := [1]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		 := uint32()<<6 + uint32()
		 = bidiIndex[]
		 := [2]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		 = uint32()<<6 + uint32()
		 = bidiIndex[]
		 := [3]
		if  < 0x80 || 0xC0 <=  {
			return Properties{}, 1
		}
		return Properties{entry: trie.lookupValue(uint32(), )}, 4
	}
	// Illegal rune
	return Properties{}, 1
}