Skip to content

Commit 5abb45e

Browse files
committed
feat: add ParseDictRef, LoadAndParseDictRef and TryLoadAndParseDictRef to work with Cell-as-value dicts
1 parent 9a4f52d commit 5abb45e

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

TonLibDotNet/Extensions/TonClientCellsDictExtensions.cs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,20 @@ public static Dictionary<TKey, TValue> LoadAndParseDict<TKey, TValue>(this Slice
7070
return ParseDict(cell, keyBitLength, keyReader, valueReader, comparer);
7171
}
7272

73+
/// <summary>
74+
/// Chains <see cref="LoadDict"/> and <see cref="ParseDictRef"/> calls and returns actual dict with data.
75+
/// </summary>
76+
/// <remarks>
77+
/// Sometimes <see href="https://github.com/ton-blockchain/dns-contract/blob/main/func/nft-item.fc#L21">arbitrary cells are stored using store_dict()</see>, so not every <see cref="LoadDict"/> result should be parsed.
78+
/// </remarks>
79+
/// <exception cref="InvalidOperationException">Dictionary is empty</exception>
80+
public static Dictionary<TKey, Cell> LoadAndParseDictRef<TKey>(this Slice slice, int keyBitLength, Func<Slice, TKey> keyReader, IEqualityComparer<TKey>? comparer = null)
81+
where TKey : notnull
82+
{
83+
var cell = LoadDict(slice);
84+
return ParseDictRef(cell, keyBitLength, keyReader, comparer);
85+
}
86+
7387
/// <summary>
7488
/// Chains <see cref="TryLoadDict"/> and <see cref="ParseDict"/> calls and returns actual dict with data (or null).
7589
/// </summary>
@@ -84,7 +98,20 @@ public static Dictionary<TKey, TValue> LoadAndParseDict<TKey, TValue>(this Slice
8498
}
8599

86100
/// <summary>
87-
/// Parses dictionary from Cell (previously loaded by <see cref="LoadDict(Slice)"/>).
101+
/// Chains <see cref="TryLoadDict"/> and <see cref="ParseDictRef"/> calls and returns actual dict with data (or null).
102+
/// </summary>
103+
/// <remarks>
104+
/// Sometimes <see href="https://github.com/ton-blockchain/dns-contract/blob/main/func/nft-item.fc#L21">arbitrary cells are stored using store_dict()</see>, so not every <see cref="TryLoadDict"/> result should be parsed.
105+
/// </remarks>
106+
public static Dictionary<TKey, Cell>? TryLoadAndParseDictRef<TKey>(this Slice slice, int keyBitLength, Func<Slice, TKey> keyReader, IEqualityComparer<TKey>? comparer = null)
107+
where TKey : notnull
108+
{
109+
var cell = TryLoadDict(slice);
110+
return cell == null ? null : ParseDictRef(cell, keyBitLength, keyReader, comparer);
111+
}
112+
113+
/// <summary>
114+
/// Parses dictionary from Cell (previously loaded by <see cref="LoadDict(Slice)"/>) where values are <see cref="Slice">Slice-based</see>.
88115
/// </summary>
89116
public static Dictionary<TKey, TValue> ParseDict<TKey, TValue>(this Cell cell, int keyBitLength, Func<Slice, TKey> keyReader, Func<Slice, TValue> valueReader, IEqualityComparer<TKey>? comparer = null)
90117
where TKey : notnull
@@ -112,6 +139,31 @@ public static Dictionary<TKey, TValue> ParseDict<TKey, TValue>(this Cell cell, i
112139
comparer);
113140
}
114141

142+
/// <summary>
143+
/// Parses dictionary from Cell (previously loaded by <see cref="LoadDict(Slice)"/>) where values are <see cref="Cell">Cells</see> (stored using dict_set_ref in FunC).
144+
/// </summary>
145+
public static Dictionary<TKey, Cell> ParseDictRef<TKey>(this Cell cell, int keyBitLength, Func<Slice, TKey> keyReader, IEqualityComparer<TKey>? comparer = null)
146+
where TKey : notnull
147+
{
148+
var items = new List<(Slice key, Slice value)>();
149+
ParseDictImpl(cell, Array.Empty<bool>(), keyBitLength, items);
150+
151+
return items.ToDictionary(
152+
x =>
153+
{
154+
var val = keyReader(x.key);
155+
x.key.EndRead();
156+
return val;
157+
},
158+
x =>
159+
{
160+
var val = x.value.LoadRef();
161+
x.value.EndRead();
162+
return val;
163+
},
164+
comparer);
165+
}
166+
115167
/// <summary>
116168
/// Stores <see cref="Cell"/> with dict data into builder.
117169
/// </summary>

0 commit comments

Comments
 (0)