func (b BitArr) String() string {
	return fmt.Sprintf("0x%s (count=%d)", hex.EncodeToString(b.Data), b.Count)
}
String returns the string representation of the bit array in hexadecimal form.
Using value receiver so printing a BitArr value will call this method.
package s2prot
import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
)
type s2pType int
const (
	s2pInt      s2pType = iota  
	s2pStruct                   
	s2pChoice                   
	s2pArr                      
	s2pBitArr                   
	s2pBlob                     
	s2pOptional                 
	s2pBool                     
	s2pFourCC                   
	s2pNull                     
)
var nameS2pTypes = map[string]s2pType{"in": s2pInt, "st": s2pStruct, "ch": s2pChoice, "ar": s2pArr,
	"bi": s2pBitArr, "bl": s2pBlob, "op": s2pOptional, "bo": s2pBool, "fo": s2pFourCC, "nu": s2pNull}
type field struct {
	name   string  
	typeid int     
	tag    int     
	isNameParent bool  
}
type typeInfo struct {
	s2pType s2pType  
	offset32 int32  
	offset64 int64  
	bits     int    
	fields []field  
	typeid int  
}
func parseTypeInfo(s string) typeInfo {
	var err error
	s = s[strings.IndexByte(s, '\'')+2:]  
	ti := typeInfo{s2pType: nameS2pTypes[s[:2]]}
	if ti.s2pType == s2pOptional {
		s = s[strings.IndexByte(s, '[')+1:]
	} else {
		s = s[strings.IndexByte(s, '[')+2:]
	}
	readBounds := func() int {
		i := strings.IndexByte(s, ',')
		j := strings.IndexByte(s, ')')
		if ti.bits, err = strconv.Atoi(s[i+1 : j]); err != nil {
			panic(err)
		}
		if ti.offset64, err = strconv.ParseInt(s[:i], 10, 64); err != nil {
			panic(err)
		}
		if ti.bits <= 32 {
			ti.offset32 = int32(ti.offset64)
		}
		return j
	}
	switch ti.s2pType {
	case s2pInt:  
		readBounds()
	case s2pStruct:  
		fields := make([]field, 0, 8)
		for {
			i := strings.IndexByte(s, '\'')
			if i < 0 {
				break  
			}
			s = s[i+1:]
			i = strings.IndexByte(s, '\'')
			f := field{name: s[:i]}
			f.isNameParent = f.name == "__parent"
			if strings.HasPrefix(f.name, "m_") {
				f.name = f.name[2:]
			}
			s = s[i+2:]
			i = strings.IndexByte(s, ',')
			j := strings.IndexByte(s, ')')
			if f.typeid, err = strconv.Atoi(s[:i]); err != nil {
				panic(err)
			}
			if f.tag, err = strconv.Atoi(s[i+1 : j]); err != nil {
				panic(err)
			}
			fields = append(fields, f)
		}
		ti.fields = make([]field, len(fields))
		copy(ti.fields, fields)
	case s2pChoice:  
		i := readBounds()
		s = s[i+1:]
		fields := make([]field, 0, 8)
		for {
			if s[1] == '}' {
				break  
			}
			s = s[2:]
			i := strings.IndexByte(s, ':')
			f := field{}
			if f.tag, err = strconv.Atoi(s[:i]); err != nil {
				panic(err)
			}
			s = s[strings.IndexByte(s, '\'')+1:]
			i = strings.IndexByte(s, '\'')
			f.name = s[:i]
			s = s[i+2:]
			i = strings.IndexByte(s, ')')
			if f.typeid, err = strconv.Atoi(s[:i]); err != nil {
				panic(err)
			}
			s = s[i:]
			fields = append(fields, f)
		}
		ti.fields = make([]field, len(fields))
		copy(ti.fields, fields)
	case s2pArr:  
		s = s[readBounds()+2:]
		j := strings.IndexByte(s, ']')
		if ti.typeid, err = strconv.Atoi(s[:j]); err != nil {
			panic(err)
		}
	case s2pBitArr:  
		readBounds()
	case s2pBlob:  
		readBounds()
	case s2pOptional:  
		j := strings.IndexByte(s, ']')
		if ti.typeid, err = strconv.Atoi(s[:j]); err != nil {
			panic(err)
		}
	case s2pBool:  
	case s2pFourCC:  
	case s2pNull:  
	}
	return ti
}
type Struct map[string]interface{}
func (s *Struct) Value(path ...string) interface{} {
	if len(path) == 0 {
		return nil
	}
	var ok bool
	ss := *s
	last := len(path) - 1
	for i := 0; i < last; i++ {
		if ss, ok = ss[path[i]].(Struct); !ok {
			return nil
		}
	}
	return ss[path[last]]
}
func (s *Struct) Structv(path ...string) (v Struct) {
	v, _ = s.Value(path...).(Struct)
	return
}
func (s *Struct) Int(path ...string) (v int64) {
	v, _ = s.Value(path...).(int64)
	return
}
func (s *Struct) Float(path ...string) (v float64) {
	v, _ = s.Value(path...).(float64)
	return
}
func (s *Struct) Bool(path ...string) (v bool) {
	v, _ = s.Value(path...).(bool)
	return
}
func (s *Struct) Bytes(path ...string) (v []byte) {
	v, _ = s.Value(path...).([]byte)
	return
}
func (s *Struct) Text(path ...string) string {
	v, ok := s.Value(path...).([]byte)
	if ok {
		return string(v)
	}
	return ""
}
func (s *Struct) Stringv(path ...string) (v string) {
	v, _ = s.Value(path...).(string)
	return
}
func (s *Struct) Array(path ...string) (v []interface{}) {
	v, _ = s.Value(path...).([]interface{})
	return
}
func (s *Struct) BitArr(path ...string) (v BitArr) {
	v, _ = s.Value(path...).(BitArr)
	return
}
func (s Struct) String() string {
	b, _ := json.MarshalIndent(s, "", "  ")
	return string(b)
}
type Event struct {
	Struct
	*EvtType  
}
func (e *Event) Loop() int64 {
	return e.Int("loop")
}
func (e *Event) UserID() int64 {
	return e.Int("userid", "userId")
}
type BitArr struct {
	Count int     
	Data  []byte  
}
var singleBitMasks = [...]byte{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}
func (b *BitArr) Bit(n int) bool {
	return b.Data[n>>3]&singleBitMasks[n&0x07] != 0
}
var ones [256]int
func init() {
	for i := range ones {
		c := 0
		for j := i; j > 0; j >>= 1 {
			if j&0x01 != 0 {
				c++
			}
		}
		ones[i] = c
	}
}
func (b *BitArr) Ones() (c int) {
	for _, d := range b.Data {
		c += ones[d]
	}
	return
}