Skip to content

Commit 9b879ee

Browse files
authored
🐛 Fix the multiple same type in a tuple will lead to incorrect field length (#93)
1 parent 46d0e5a commit 9b879ee

File tree

6 files changed

+39
-30
lines changed

6 files changed

+39
-30
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ that can be found in the LICENSE file. -->
44

55
# Changelog
66

7+
## 1.0.0-dev.35
8+
9+
- Fix the multiple same type in a tuple will lead to incorrect field length.
10+
711
## 1.0.0-dev.34
812

913
- Handles IDL nested vec class encoding.

packages/agent_dart/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: agent_dart
2-
version: 1.0.0-dev.34
2+
version: 1.0.0-dev.35
33

44
description: |
55
An agent library built for Internet Computer,

packages/agent_dart_base/lib/candid/idl.dart

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:convert';
44
import 'dart:math' as math;
55
import 'dart:typed_data';
66

7+
import 'package:collection/collection.dart';
78
import 'package:meta/meta.dart';
89

910
import '../agent/agent.dart';
@@ -1026,16 +1027,19 @@ class RecordClass extends ConstructType<Map> {
10261027

10271028
class TupleClass<T extends List> extends ConstructType<List> {
10281029
TupleClass(List<CType> components) : _components = components {
1029-
_fields = Map.from(_makeMap(components)).entries.toList();
1030-
_fields.sort(
1031-
(a, b) => idlLabelToId(a.key).toInt() - idlLabelToId(b.key).toInt(),
1032-
);
1030+
_fields = components.mapIndexed(_makeField).sorted(
1031+
(a, b) => idlLabelToId(a.key).toInt() - idlLabelToId(b.key).toInt(),
1032+
);
10331033
}
10341034

10351035
final List<CType> _components;
10361036

1037-
List<MapEntry> get fields => _fields;
1038-
late final List<MapEntry> _fields;
1037+
List<MapEntry<String, CType>> get fields => _fields;
1038+
late final List<MapEntry<String, CType>> _fields;
1039+
1040+
MapEntry<String, CType> _makeField(int index, CType component) {
1041+
return MapEntry('_${index}_', component);
1042+
}
10391043

10401044
@override
10411045
R accept<D, R>(Visitor<D, R> v, D d) {
@@ -1050,9 +1054,7 @@ class TupleClass<T extends List> extends ConstructType<List> {
10501054
// `>=` because tuples can be covariant when encoded.
10511055
return x.length >= _fields.length &&
10521056
_components
1053-
.asMap()
1054-
.entries
1055-
.map((t) => t.value.covariant(x[t.key]) ? 0 : 1)
1057+
.mapIndexed((index, value) => value.covariant(x[index]) ? 0 : 1)
10561058
.reduce((value, element) => value + element) ==
10571059
0;
10581060
}
@@ -1099,10 +1101,7 @@ class TupleClass<T extends List> extends ConstructType<List> {
10991101
);
11001102
}
11011103
final res = [];
1102-
for (final entry in tuple._components.asMap().entries) {
1103-
// [i, wireType]
1104-
final i = entry.key;
1105-
final wireType = entry.value;
1104+
for (final (i, wireType) in tuple._components.indexed) {
11061105
if (i >= _components.length) {
11071106
// skip value
11081107
wireType.decodeValue(x, wireType);
@@ -1134,12 +1133,6 @@ class TupleClass<T extends List> extends ConstructType<List> {
11341133
final fields = _fields.map((entry) => '${entry.key}:${entry.value.name}');
11351134
return "record {${fields.join('; ')}}";
11361135
}
1137-
1138-
Map<String, dynamic> _makeMap(List<CType> components) {
1139-
return {
1140-
for (final e in components) '_${components.indexOf(e)}_': e,
1141-
};
1142-
}
11431136
}
11441137

11451138
class VariantClass extends ConstructType<Map<String, dynamic>> {
@@ -1408,7 +1401,7 @@ class FuncClass extends ConstructType<List> {
14081401
'Arity mismatch',
14091402
);
14101403
}
1411-
return '(${types.asMap().entries.map((e) => e.value.valueToString(v[e.key])).join(', ')})';
1404+
return '(${types.mapIndexed((i, e) => e.valueToString(v[i])).join(', ')})';
14121405
}
14131406

14141407
@override
@@ -1868,22 +1861,21 @@ List idlDecode(List<CType> retTypes, Uint8List bytes) {
18681861
}
18691862
}
18701863

1871-
rawTable.asMap().forEach((i, entry) {
1872-
final t = buildType(entry);
1864+
for (final (i, e) in rawTable.indexed) {
1865+
final t = buildType(e);
18731866
table[i].fill(t);
1874-
});
1867+
}
18751868

18761869
final types = rawTypes.map((t) => getType(t)).toList();
18771870

1878-
final output = retTypes.asMap().entries.map((entry) {
1879-
final result = entry.value.decodeValue(b, types[entry.key]);
1880-
return result;
1881-
}).toList();
1871+
final output =
1872+
retTypes.mapIndexed((i, e) => e.decodeValue(b, types[i])).toList();
18821873

18831874
// Skip unused values.
18841875
for (int ind = retTypes.length; ind < types.length; ind++) {
18851876
types[ind].decodeValue(b, types[ind]);
18861877
}
1878+
18871879
if (b.buffer.isNotEmpty) {
18881880
throw StateError('Unexpected left-over bytes.');
18891881
}

packages/agent_dart_base/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: agent_dart_base
2-
version: 1.0.0-dev.34
2+
version: 1.0.0-dev.35
33

44
description: The Dart plugin that bridges Rust implementation for agent_dart.
55
repository: https://github.com/AstroxNetwork/agent_dart

packages/agent_dart_base/test/candid/idl.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,19 @@ void idlTest() {
275275
]),
276276
throwsA(isError<ArgumentError>()),
277277
);
278+
expect(
279+
IDL.encode(
280+
[
281+
IDL.Tuple([IDL.Text, IDL.Text])
282+
],
283+
[
284+
['a', 'b']
285+
],
286+
),
287+
Uint8List.fromList(
288+
[68, 73, 68, 76, 1, 108, 2, 0, 113, 1, 113, 1, 0, 1, 97, 1, 98],
289+
),
290+
);
278291
});
279292

280293
test('IDL encoding (arraybuffer)', () {

packages/agent_dart_ffi/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: agent_dart_ffi
2-
version: 1.0.0-dev.34
2+
version: 1.0.0-dev.35
33

44
description: The FFI plugin that bridges Rust implementation for agent_dart.
55
repository: https://github.com/AstroxNetwork/agent_dart

0 commit comments

Comments
 (0)