func TestFlags(t *testing.T) { type td struct { count int bits uint name string } tests := []td{ {_FLAG_ACC_COUNT, FLAG_ACC_BITS, "Access"}, {_FLAG_TYPE_COUNT, FLAG_TYPE_BITS, "Type"}, {_FLAG_LANG_COUNT, FLAG_LANG_BITS, "Language"}, {1 << _FLAG_BOOL_COUNT, _FLAG_BOOL_COUNT, "Bool"}, } totSize := 0 for _, test := range tests { if current, actual := test.bits, util.Bits(test.count); actual != current { t.Errorf("Bit mismatch for %s bits: %d != %d", test.name, current, actual) } totSize += int(test.bits) } var f Flags ty := reflect.TypeOf(f) if bits := ty.Bits(); totSize > bits { t.Errorf("The number of bits used does not fit in %s's size: %d > %d", ty.Name(), totSize, bits) } t.Logf("Bits used: %d", totSize) }
func (m *MetadataUtil) Size(t reflect.Type) (uint, error) { size := uint(0) name := t.Name() switch name { case "StringIndex": size = uint(m.StringHeap.RowSize) case "Guid": size = uint(m.GuidHeap.RowSize) case "BlobIndex": size = uint(m.BlobHeap.RowSize) default: if strings.HasSuffix(name, "EncodedIndex") { id := idx_name_lut[name] var ( tables = enc_lut[id] rows uint32 ) for _, t := range tables { if t == id_nullTable { continue } if s2 := m.Tables[t].Rows; s2 > rows { rows = s2 } } if rows<<util.Bits(len(tables)) < 1<<16 { size = 2 } else { size = 4 } } else if strings.HasSuffix(name, "Index") { if m.Tables[idx_name_lut[name]].Rows < 1<<16 { size = 2 } else { size = 4 } } else { switch t.Kind() { case reflect.Struct: for i := 0; i < t.NumField(); i++ { f := t.Field(i) if s, err := m.Size(f.Type); err != nil { return 0, err } else { size += s } } case reflect.Uint8: return 1, nil case reflect.Uint16: return 2, nil case reflect.Uint32: return 4, nil case reflect.Uint64: return 8, nil default: return 0, errors.New(fmt.Sprintf("Don't know the size of: %s, %s", t.Name(), t.Kind())) } } } return size, nil }
func (m *MetadataUtil) Create(br *binary.BinaryReader, v interface{}) error { t := reflect.ValueOf(v) if t.Kind() != reflect.Ptr { return errors.New(fmt.Sprintf("Expected a pointer not %s", t.Kind())) } v2 := t.Elem() name := v2.Type().Name() if name == "StringIndex" { size := m.StringHeap.RowSize index, err := m.ReadIndex(br, uint(size)) if err != nil { return err } data := m.StringHeap.data[index:m.StringHeap.Rows] for i := range data { if data[i] == '\u0000' { data = data[:i] break } } v2.SetString(string(data)) } else if name == "Guid" { size := m.GuidHeap.RowSize if index, err := m.ReadIndex(br, uint(size)); err != nil { return err } else if index != 0 { index = (index - 1) * 16 g := Guid(m.GuidHeap.data[index : index+16]) v2.Set(reflect.ValueOf(g)) } } else if strings.HasSuffix(name, "EncodedIndex") { size, err := m.Size(v2.Type()) if err != nil { return err } idx, err := m.ReadIndex(br, size) if err != nil { return err } var ( tables = enc_lut[idx_name_lut[name]] b = util.Bits(len(tables)) mask = uint32(0xffff << b) tbl = idx &^ mask ti ConcreteTableIndex ) idx = idx >> b ti.index = idx ti.table = tables[int(tbl)] ti.metadataUtil = m v2.Set(reflect.ValueOf(&ti)) } else if strings.HasSuffix(name, "Index") { size, err := m.Size(v2.Type()) if err != nil { return err } var ti ConcreteTableIndex if ti.index, err = m.ReadIndex(br, size); err != nil { return err } if name == "BlobIndex" { ti.table = id_Blob } else { ti.table = idx_name_lut[name] } ti.metadataUtil = m v2.Set(reflect.ValueOf(&ti)) } else { if v2.Kind() != reflect.Struct { return br.ReadInterface(v) } for i := 0; i < v2.NumField(); i++ { f := v2.Field(i) a := f.Addr() if err := m.Create(br, a.Interface()); err != nil { return err } } } return nil }