diff --git a/CHANGELOG.md b/CHANGELOG.md index 83001afc..8f8539a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ that can be found in the LICENSE file. --> # Changelog +## 1.0.0-dev.34 + +- Handles IDL nested vec class encoding. + ## 1.0.0-dev.33 - Use an explicit serialization method rather than `toJson`. diff --git a/packages/agent_dart/pubspec.yaml b/packages/agent_dart/pubspec.yaml index 6c7ff0f7..fe42e464 100644 --- a/packages/agent_dart/pubspec.yaml +++ b/packages/agent_dart/pubspec.yaml @@ -1,5 +1,5 @@ name: agent_dart -version: 1.0.0-dev.33 +version: 1.0.0-dev.34 description: | An agent library built for Internet Computer, diff --git a/packages/agent_dart_base/lib/candid/idl.dart b/packages/agent_dart_base/lib/candid/idl.dart index 5238ee20..a2cf25f2 100644 --- a/packages/agent_dart_base/lib/candid/idl.dart +++ b/packages/agent_dart_base/lib/candid/idl.dart @@ -49,6 +49,21 @@ List zipWith( } Uint8List? tryToJson(CType type, dynamic value) { + if (type is VecClass> && + value is List && + type.covariant(value)) { + try { + final list = value as List; + try { + value = list.map((e) => e.toIDLSerializable()).toList(growable: false); + } on NoSuchMethodError { + value = list.map((e) => e.toJson()).toList(growable: false); + } + return type.encodeValue(value); + } catch (e) { + return null; + } + } if ((type is RecordClass || type is VariantClass || (type is TextClass && value is! String)) && diff --git a/packages/agent_dart_base/pubspec.yaml b/packages/agent_dart_base/pubspec.yaml index fc11eaca..6bac3b76 100644 --- a/packages/agent_dart_base/pubspec.yaml +++ b/packages/agent_dart_base/pubspec.yaml @@ -1,5 +1,5 @@ name: agent_dart_base -version: 1.0.0-dev.33 +version: 1.0.0-dev.34 description: The Dart plugin that bridges Rust implementation for agent_dart. repository: https://github.com/AstroxNetwork/agent_dart diff --git a/packages/agent_dart_base/test/candid/idl.dart b/packages/agent_dart_base/test/candid/idl.dart index e37245a5..f11acf7f 100644 --- a/packages/agent_dart_base/test/candid/idl.dart +++ b/packages/agent_dart_base/test/candid/idl.dart @@ -1,12 +1,12 @@ import 'dart:typed_data'; import 'package:agent_dart_base/agent_dart_base.dart'; +import 'package:collection/collection.dart'; import 'package:test/test.dart'; import '../test_utils.dart'; void main() { - ffiInit(); idlTest(); } @@ -399,19 +399,43 @@ void idlTest() { ); final foobar = FooBar.fromJson({'foo': '💩', 'bar': BigInt.from(42)}); - final encode = IDL.encode([ + final encodedFoobar = IDL.encode([ IDL.Opt(IDL.Record({'foo': IDL.Text, 'bar': IDL.Int})), ], [ [foobar], ]); - final decode = IDL.decode( + final decodedFooBar = IDL.decode( [ IDL.Opt(IDL.Record({'foo': IDL.Text, 'bar': IDL.Int})), ], - encode, + encodedFoobar, ); - final newFoobar = FooBar.fromJson((decode.first as List).first); + final newFoobar = FooBar.fromJson((decodedFooBar.first as List).first); expect(foobar, newFoobar); + + const fooArgs = FooArgs(types: FooTypes.values); + final encodedFooArgs = IDL.encode( + [ + IDL.Record({ + 'types': OptClass( + VecClass(VariantClass({'Type1': IDL.Null, 'Type2': IDL.Null})), + ) + }), + ], + [fooArgs], + ); + final decodedFooArgs = IDL.decode( + [ + IDL.Record({ + 'types': OptClass( + VecClass(VariantClass({'Type1': IDL.Null, 'Type2': IDL.Null})), + ) + }), + ], + encodedFooArgs, + ); + final newFooArgs = FooArgs.fromJson(decodedFooArgs.first); + expect(fooArgs, newFooArgs); }); test('IDL decoding (skip fields)', () { @@ -800,3 +824,56 @@ class FooBar { @override int get hashCode => foo.hashCode ^ bar.hashCode; } + +enum FooTypes { + type1('Type1'), + type2('Type2'); + + const FooTypes(this.name); + + factory FooTypes.fromJson(Map json) { + final key = json.keys.first; + return FooTypes.values.firstWhere((e) => e.name == key); + } + + final String name; + + Map toJson() { + return {name: null}; + } +} + +class FooArgs { + const FooArgs({this.types}); + + factory FooArgs.fromJson(Map json) { + return FooArgs( + types: (json['types'] as List).map((e) { + return (e as List?)?.map((e) { + return FooTypes.fromJson(e); + }).toList(); + }).firstOrNull, + ); + } + + final List? types; + + Map toJson() { + final types = this.types; + return { + 'types': [if (types != null) types], + }; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is FooArgs && + const DeepCollectionEquality().equals(other.types, types)); + } + + @override + int get hashCode => + Object.hashAll([runtimeType, const DeepCollectionEquality().hash(types)]); +} diff --git a/packages/agent_dart_ffi/pubspec.yaml b/packages/agent_dart_ffi/pubspec.yaml index af9f0b01..f85a6800 100644 --- a/packages/agent_dart_ffi/pubspec.yaml +++ b/packages/agent_dart_ffi/pubspec.yaml @@ -1,5 +1,5 @@ name: agent_dart_ffi -version: 1.0.0-dev.33 +version: 1.0.0-dev.34 description: The FFI plugin that bridges Rust implementation for agent_dart. repository: https://github.com/AstroxNetwork/agent_dart