Skip to content

Commit

Permalink
Fix after review.
Browse files Browse the repository at this point in the history
  • Loading branch information
andreibancioiu committed Aug 31, 2023
1 parent a79a6e8 commit 56edcd6
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 60 deletions.
108 changes: 63 additions & 45 deletions src/smartcontracts/argSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,42 +68,48 @@ export class ArgSerializer {

// This is a recursive function.
function readValue(type: Type): TypedValue {
// TODO: Use matchers.

if (type.hasExactClass(OptionalType.ClassName)) {
let typedValue = readValue(type.getFirstTypeParameter());
const typedValue = readValue(type.getFirstTypeParameter());
return new OptionalValue(type, typedValue);
} else if (type.hasExactClass(VariadicType.ClassName)) {
const variadicType = <VariadicType>type;
const typedValues = [];

if (variadicType.isCounted) {
const count: number = readValue(new U32Type()).valueOf().toNumber();
}

for (let i = 0; i < count; i++) {
typedValues.push(readValue(type.getFirstTypeParameter()));
}
} else {
while (!hasReachedTheEnd()) {
typedValues.push(readValue(type.getFirstTypeParameter()));
}
}
if (type.hasExactClass(VariadicType.ClassName)) {
return readVariadicValue(type);
}

return new VariadicValue(variadicType, typedValues);
} else if (type.hasExactClass(CompositeType.ClassName)) {
let typedValues = [];
if (type.hasExactClass(CompositeType.ClassName)) {
const typedValues = [];

for (const typeParameter of type.getTypeParameters()) {
typedValues.push(readValue(typeParameter));
}

return new CompositeValue(type, typedValues);
}

// Non-composite (singular), non-variadic (fixed) type.
// The only branching without a recursive call.
const typedValue = decodeNextBuffer(type);
return typedValue!;
}

function readVariadicValue(type: Type): TypedValue {
const variadicType = <VariadicType>type;
const typedValues = [];

if (variadicType.isCounted) {
const count: number = readValue(new U32Type()).valueOf().toNumber();

for (let i = 0; i < count; i++) {
typedValues.push(readValue(type.getFirstTypeParameter()));
}
} else {
// Non-composite (singular), non-variadic (fixed) type.
// The only branching without a recursive call.
let typedValue = decodeNextBuffer(type);
return typedValue!;
while (!hasReachedTheEnd()) {
typedValues.push(readValue(type.getFirstTypeParameter()));
}
}

return new VariadicValue(variadicType, typedValues);
}

function decodeNextBuffer(type: Type): TypedValue | null {
Expand Down Expand Up @@ -150,43 +156,55 @@ export class ArgSerializer {
// TODO: Refactor, split (function is quite complex).
const self = this;

let buffers: Buffer[] = [];
const buffers: Buffer[] = [];

for (const value of values) {
handleValue(value);
}

// This is a recursive function. It appends to the "buffers" variable.
function handleValue(value: TypedValue): void {
// TODO: Use matchers.

if (value.hasExactClass(OptionalValue.ClassName)) {
let valueAsOptional = <OptionalValue>value;
const valueAsOptional = <OptionalValue>value;

if (valueAsOptional.isSet()) {
handleValue(valueAsOptional.getTypedValue());
}
} else if (value.hasExactClass(VariadicValue.ClassName)) {
const valueAsVariadic = <VariadicValue>value;
const variadicType = <VariadicType>valueAsVariadic.getType();

if (variadicType.isCounted) {
const countValue = new U32Value(valueAsVariadic.getItems().length);
buffers.push(self.codec.encodeTopLevel(countValue));
}
return;
}

if (value.hasExactClass(VariadicValue.ClassName)) {
handleVariadicValue(<VariadicValue>value);
return;
}

if (value.hasExactClass(CompositeValue.ClassName)) {
const valueAsComposite = <CompositeValue>value;

for (const item of valueAsVariadic.getItems()) {
handleValue(item);
}
} else if (value.hasExactClass(CompositeValue.ClassName)) {
let valueAsComposite = <CompositeValue>value;
for (const item of valueAsComposite.getItems()) {
handleValue(item);
}
} else {
// Non-composite (singular), non-variadic (fixed) type.
// The only branching without a recursive call.
let buffer: Buffer = self.codec.encodeTopLevel(value);
buffers.push(buffer);

return
}

// Non-composite (singular), non-variadic (fixed) type.
// The only branching without a recursive call.
const buffer: Buffer = self.codec.encodeTopLevel(value);
buffers.push(buffer);
}

function handleVariadicValue(value: VariadicValue): void {
const variadicType = <VariadicType>value.getType();

if (variadicType.isCounted) {
const countValue = new U32Value(value.getItems().length);
buffers.push(self.codec.encodeTopLevel(countValue));
}

for (const item of value.getItems()) {
handleValue(item);
}
}

Expand Down
25 changes: 10 additions & 15 deletions src/smartcontracts/nativeSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,18 @@ export namespace NativeSerializer {
// Furthermore, multiple counted-variadic arguments cannot be expressed in the current variant.
// E.g. now, it's unreasonable to decide that `foo([1, 2, 3, "a", "b", "c"])` calls `foo(counted-variadic<int>, counted-variadic<string>)`.
function repackNonCountedVariadicParameters(args: any[], endpoint: EndpointDefinition) {
let parameters = endpoint.input;

// TODO: Remove after first review. Temporarily left this way to make the review easier.
if (true) {
const lastEndpointParamIndex = parameters.length - 1;
const argAtIndex = args[lastEndpointParamIndex];

if (argAtIndex?.belongsToTypesystem) {
const isVariadicValue = argAtIndex.hasClassOrSuperclass(VariadicValue.ClassName);
if (!isVariadicValue) {
throw new ErrInvalidArgument(`Wrong argument type for endpoint ${endpoint.name}: typed value provided; expected variadic type, have ${argAtIndex.getClassName()}`);
}
const lastEndpointParamIndex = endpoint.input.length - 1;
const argAtIndex = args[lastEndpointParamIndex];

// Do not repack.
} else {
args[lastEndpointParamIndex] = args.slice(lastEndpointParamIndex);
if (argAtIndex?.belongsToTypesystem) {
const isVariadicValue = argAtIndex.hasClassOrSuperclass(VariadicValue.ClassName);
if (!isVariadicValue) {
throw new ErrInvalidArgument(`Wrong argument type for endpoint ${endpoint.name}: typed value provided; expected variadic type, have ${argAtIndex.getClassName()}`);
}

// Do not repack.
} else {
args[lastEndpointParamIndex] = args.slice(lastEndpointParamIndex);
}

return args;
Expand Down

0 comments on commit 56edcd6

Please sign in to comment.