Skip to content

Commit

Permalink
🐛 Handles nested vec class encoding (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexV525 authored Jan 6, 2025
1 parent fd5e968 commit 46d0e5a
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
2 changes: 1 addition & 1 deletion packages/agent_dart/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
15 changes: 15 additions & 0 deletions packages/agent_dart_base/lib/candid/idl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ List<TR> zipWith<TX, TY, TR>(
}

Uint8List? tryToJson(CType type, dynamic value) {
if (type is VecClass<Map<String, dynamic>> &&
value is List<Enum> &&
type.covariant(value)) {
try {
final list = value as List<dynamic>;
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)) &&
Expand Down
2 changes: 1 addition & 1 deletion packages/agent_dart_base/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
87 changes: 82 additions & 5 deletions packages/agent_dart_base/test/candid/idl.dart
Original file line number Diff line number Diff line change
@@ -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();
}

Expand Down Expand Up @@ -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)', () {
Expand Down Expand Up @@ -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<String, Null> 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<FooTypes>? types;

Map<String, dynamic> 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)]);
}
2 changes: 1 addition & 1 deletion packages/agent_dart_ffi/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit 46d0e5a

Please sign in to comment.