Skip to content

Commit

Permalink
tlb: load dictionary into the map
Browse files Browse the repository at this point in the history
  • Loading branch information
iam047801 committed Oct 15, 2023
1 parent 0556e91 commit 5d66868
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
36 changes: 35 additions & 1 deletion tlb/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,41 @@ func loadFromCell(v any, slice *cell.Slice, skipProofBranches, skipMagic bool) e
}
}

setVal(reflect.ValueOf(dict))
if len(settings) < 4 || settings[2] != "->" {
setVal(reflect.ValueOf(dict))
continue
}
if structField.Type.Kind() != reflect.Map {
return fmt.Errorf("can map dictionary only into the map")
}
if structField.Type.Key() != reflect.TypeOf("") {
return fmt.Errorf("can map dictionary only into the map with string key")
}

mappedDict := reflect.MakeMapWithSize(reflect.MapOf(structField.Type.Key(), structField.Type.Elem()), 0)
for _, kv := range dict.All() {
dictK, err := kv.Key.BeginParse().LoadBigUInt(uint(sz))
if err != nil {
return fmt.Errorf("failed to load dict key for %s: %w", structField.Name, err)
}

dictVT := reflect.StructOf([]reflect.StructField{{
Name: "Value",
Type: structField.Type.Elem(),
Tag: reflect.StructTag(fmt.Sprintf("tlb:%q", strings.Join(settings[3:], " "))),
}})

dictV := reflect.New(dictVT).Interface()

err = loadFromCell(dictV, kv.Value.BeginParse(), skipProofBranches, false)
if err != nil {
return fmt.Errorf("failed to load dict value for %v: %w", structField.Name, err)
}

mappedDict.SetMapIndex(reflect.ValueOf(dictK.String()), reflect.ValueOf(dictV).Elem().Field(0))
}

setVal(mappedDict)
continue
} else if settings[0] == "var" {
if settings[1] == "uint" {
Expand Down
39 changes: 39 additions & 0 deletions tlb/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,42 @@ func TestLoadFromCell(t *testing.T) {
t.Fatal("cell hashes not same after From to")
}
}

func TestLoadFromCell_MappedDict(t *testing.T) {
dict := cell.NewDict(3)

b := cell.BeginCell()

err := b.StoreBoolBit(true)
if err != nil {
t.Fatal(err)
}

err = dict.SetIntKey(big.NewInt(1), b.EndCell())
if err != nil {
t.Fatal(err)
}

b = cell.BeginCell()
if err := b.StoreDict(dict); err != nil {
t.Fatal(err)
}

var ret struct {
Value map[string]bool `tlb:"dict 3 -> bool"`
}

err = LoadFromCell(&ret, b.EndCell().BeginParse())
if err != nil {
t.Fatal(err)
}

j, err := json.Marshal(ret)
if err != nil {
t.Fatal(err)
}

if string(j) != "{\"Value\":{\"1\":true}}" {
t.Fatal("wrong map json")
}
}

0 comments on commit 5d66868

Please sign in to comment.