-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non-breaking change: add support for "counted-variadic" #323
Conversation
function repackNonCountedVariadicParameters(args: any[], endpoint: EndpointDefinition) { | ||
let parameters = endpoint.input; | ||
|
||
// TODO: Remove after first review. Temporarily left this way to make the review easier. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (true)
after first review!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
return this.createFromItems(items, false); | ||
} | ||
|
||
static fromItemsCounted(...items: TypedValue[]): VariadicValue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New utility function.
@@ -76,11 +74,11 @@ describe("test mapper", () => { | |||
assert.deepEqual(mappedType, new ArrayVecType(size, typeParameter)); | |||
} | |||
|
|||
function testMapping(expression: string, constructor: TypeConstructor, typeParameters: Type[] = []) { | |||
function testMapping(expression: string, expectedType: Type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a refactoring, simplification in this tests file.
src/smartcontracts/argSerializer.ts
Outdated
typedValues.push(readValue(type.getFirstTypeParameter())); | ||
} | ||
} else { | ||
while (!hasReachedTheEnd()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-counted variadic arguments (regular variadic arguments) can only be at the tail of the arguments.
src/smartcontracts/argSerializer.ts
Outdated
|
||
if (variadicType.isCounted) { | ||
const countValue = new U32Value(valueAsVariadic.getItems().length); | ||
buffers.push(self.codec.encodeTopLevel(countValue)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@count@var1@var2@var3
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the variadic arg handling can be pulled into a function so we have less complexity in the if/else branches.
Q: do you like the else if {}
approach better? Since every branch returns, we could also have less indenting doing:
if (condition) {
...
return result
}
if (condition2) {
...
return result2;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, fixed. Extracted handling into separate (though "nested") functions. Also re-organized branches for less indenting 👍
const endpoint = new EndpointDefinition("foo", inputParameters, [], endpointModifiers); | ||
|
||
// Implicit counted-variadic (not supported). | ||
assert.throws(() => NativeSerializer.nativeToTypedValues([8, 9, 10, "a", "b", "c"], endpoint), ErrInvalidArgument); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot be supported in the current implementation of the NativeSerializer
, due to args-packing ambiguity.
VariadicValue.fromItemsCounted(new U32Value(8), new U32Value(9), new U32Value(10)), | ||
VariadicValue.fromItemsCounted(BytesValue.fromUTF8("a"), BytesValue.fromUTF8("b"), BytesValue.fromUTF8("c")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible to have multiple counted variadic arguments (users are required to pass them in the explicitly typed form).
if (hasNonCountedVariadicParameter(endpoint)) { | ||
args = repackNonCountedVariadicParameters(args, endpoint); | ||
} else { | ||
// Repacking makes sense (it's possible) only for regular, non-counted variadic parameters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No repacking: there are no regular (non-counted) variadic parameters.
function toVariadicValue(native: any, type: Type, errorContext: ArgumentErrorContext): TypedValue { | ||
function toVariadicValue(native: any, type: VariadicType, errorContext: ArgumentErrorContext): TypedValue { | ||
if (type.isCounted) { | ||
throw new ErrInvalidArgument(`Counted variadic arguments must be explicitly typed. E.g. use "VariadicValue.fromItemsCounted()" or "new VariadicValue()"`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In other words, the type inference system won't perform any type inference for counted-variadic
.
@@ -2,6 +2,20 @@ import { Type, TypeCardinality, TypedValue, TypePlaceholder } from "./types"; | |||
|
|||
export class VariadicType extends Type { | |||
static ClassName = "VariadicType"; | |||
public readonly isCounted: boolean; | |||
|
|||
constructor(typeParameter: Type, isCounted: boolean = false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Theoretically, not a breaking change.
Related (examples): multiversx/mx-sdk-js-examples#27. |
Should fix: #316.
ArgsSerializer
and the type inference system have been adjusted to handlecounted-variadic
arguments, as well. Though, note that (due to constraints brought by the current implementation of the type inference system) counted variadic arguments must be explicitly typed when calling contract methods. E.g.Or:
In order to create a
counted-variadic
type, passtrue
as the second parameter for theVariadicType
constructor. E.g.