diff --git a/abi/field.go b/abi/field.go new file mode 100644 index 0000000..d1efd90 --- /dev/null +++ b/abi/field.go @@ -0,0 +1,7 @@ +package abi + +// Field is a field in a struct, enum etc. +type Field struct { + Name string + Value SingleValue +} diff --git a/abi/multiValues.go b/abi/multiValues.go new file mode 100644 index 0000000..28b92ae --- /dev/null +++ b/abi/multiValues.go @@ -0,0 +1,17 @@ +package abi + +// MultiValue is a multi-value +type MultiValue struct { + Items []any +} + +// VariadicValues holds variadic values +type VariadicValues struct { + Items []any + ItemCreator func() any +} + +// OptionalValue holds an optional value +type OptionalValue struct { + Value any +} diff --git a/abi/serializer.go b/abi/serializer.go index 8de780a..39aa1d9 100644 --- a/abi/serializer.go +++ b/abi/serializer.go @@ -3,6 +3,7 @@ package abi import ( "encoding/hex" "errors" + "fmt" "strings" ) @@ -62,7 +63,7 @@ func (s *serializer) doSerialize(partsHolder *partsHolder, inputValues []any) er } switch value := value.(type) { - case InputOptionalValue: + case *OptionalValue: if i != len(inputValues)-1 { // Usage of multiple optional values is not recommended: // https://docs.multiversx.com/developers/data/multi-values @@ -70,15 +71,17 @@ func (s *serializer) doSerialize(partsHolder *partsHolder, inputValues []any) er return errors.New("an optional value must be last among input values") } - err = s.serializeInputOptionalValue(partsHolder, value) - case InputMultiValue: - err = s.serializeInputMultiValue(partsHolder, value) - case InputVariadicValues: + if value.Value != nil { + err = s.doSerialize(partsHolder, []any{value.Value}) + } + case *MultiValue: + err = s.doSerialize(partsHolder, value.Items) + case *VariadicValues: if i != len(inputValues)-1 { return errors.New("variadic values must be last among input values") } - err = s.serializeInputVariadicValues(partsHolder, value) + err = s.doSerialize(partsHolder, value.Items) case SingleValue: partsHolder.appendEmptyPart() err = s.serializeSingleValue(partsHolder, value) @@ -124,7 +127,7 @@ func (s *serializer) doDeserialize(partsHolder *partsHolder, outputValues []any) } switch value := value.(type) { - case *OutputOptionalValue: + case *OptionalValue: if i != len(outputValues)-1 { // Usage of multiple optional values is not recommended: // https://docs.multiversx.com/developers/data/multi-values @@ -132,14 +135,19 @@ func (s *serializer) doDeserialize(partsHolder *partsHolder, outputValues []any) return errors.New("an optional value must be last among output values") } - err = s.deserializeOutputOptionalValue(partsHolder, value) - case *OutputMultiValue: - err = s.deserializeOutputMultiValue(partsHolder, value) - case *OutputVariadicValues: + if partsHolder.isFocusedBeyondLastPart() { + value.Value = nil + } else { + err = s.doDeserialize(partsHolder, []any{value.Value}) + } + case *MultiValue: + err = s.doDeserialize(partsHolder, value.Items) + case *VariadicValues: if i != len(outputValues)-1 { return errors.New("variadic values must be last among output values") } + err = s.deserializeVariadicValues(partsHolder, value) case SingleValue: err = s.deserializeSingleValue(partsHolder, value) default: @@ -154,36 +162,6 @@ func (s *serializer) doDeserialize(partsHolder *partsHolder, outputValues []any) return nil } -func (s *serializer) serializeInputOptionalValue(partsHolder *partsHolder, value InputOptionalValue) error { - if value.Value == nil { - return nil - } - - return s.doSerialize(partsHolder, []any{value.Value}) -} - -func (s *serializer) serializeInputMultiValue(partsHolder *partsHolder, value InputMultiValue) error { - for _, item := range value.Items { - err := s.doSerialize(partsHolder, []any{item}) - if err != nil { - return err - } - } - - return nil -} - -func (s *serializer) serializeInputVariadicValues(partsHolder *partsHolder, value InputVariadicValues) error { - for _, item := range value.Items { - err := s.doSerialize(partsHolder, []any{item}) - if err != nil { - return err - } - } - - return nil -} - func (s *serializer) serializeSingleValue(partsHolder *partsHolder, value SingleValue) error { data, err := s.codec.EncodeTopLevel(value) if err != nil { @@ -193,32 +171,7 @@ func (s *serializer) serializeSingleValue(partsHolder *partsHolder, value Single return partsHolder.appendToLastPart(data) } -func (s *serializer) deserializeOutputOptionalValue(partsHolder *partsHolder, value *OutputOptionalValue) error { - for partsHolder.isFocusedBeyondLastPart() { - value.Value = nil - return nil - } - - err := s.doDeserialize(partsHolder, []any{value.Value}) - if err != nil { - return err - } - - return nil -} - -func (s *serializer) deserializeOutputMultiValue(partsHolder *partsHolder, value *OutputMultiValue) error { - for _, item := range value.Items { - err := s.doDeserialize(partsHolder, []any{item}) - if err != nil { - return err - } - } - - return nil -} - -func (s *serializer) deserializeOutputVariadicValues(partsHolder *partsHolder, value *OutputVariadicValues) error { +func (s *serializer) deserializeVariadicValues(partsHolder *partsHolder, value *VariadicValues) error { if value.ItemCreator == nil { return errors.New("cannot deserialize variadic values: item creator is nil") } diff --git a/abi/valuesMulti.go b/abi/valuesMulti.go deleted file mode 100644 index b938422..0000000 --- a/abi/valuesMulti.go +++ /dev/null @@ -1,32 +0,0 @@ -package abi - -// InputMultiValue is a multi-value (used for encoding) -type InputMultiValue struct { - Items []any -} - -// OutputMultiValue is a multi-value (used for decoding) -type OutputMultiValue struct { - Items []any -} - -// InputVariadicValues holds variadic values (used for encoding) -type InputVariadicValues struct { - Items []any -} - -// OutputVariadicValues holds variadic values (used for decoding) -type OutputVariadicValues struct { - Items []any - ItemCreator func() any -} - -// InputOptionalValue holds an optional value (used for encoding) -type InputOptionalValue struct { - Value any -} - -// OutputOptionalValue holds an optional value (used for decoding) -type OutputOptionalValue struct { - Value any -} diff --git a/abi/valuesSingle.go b/abi/valuesSingle.go deleted file mode 100644 index cfbd070..0000000 --- a/abi/valuesSingle.go +++ /dev/null @@ -1,106 +0,0 @@ -package abi - -import "math/big" - -// U8Value is a wrapper for uint8 -type U8Value struct { - Value uint8 -} - -// U16Value is a wrapper for uint16 -type U16Value struct { - Value uint16 -} - -// U32Value is a wrapper for uint32 -type U32Value struct { - Value uint32 -} - -// U64Value is a wrapper for uint64 -type U64Value struct { - Value uint64 -} - -// I8Value is a wrapper for int8 -type I8Value struct { - Value int8 -} - -// I16Value is a wrapper for int16 -type I16Value struct { - Value int16 -} - -// I32Value is a wrapper for int32 -type I32Value struct { - Value int32 -} - -// I64Value is a wrapper for int64 -type I64Value struct { - Value int64 -} - -// BigUIntValue is a wrapper for a big integer (unsigned) -type BigUIntValue struct { - Value *big.Int -} - -// BigIntValue is a wrapper for a big integer (signed) -type BigIntValue struct { - Value *big.Int -} - -// AddressValue is a wrapper for an address -type AddressValue struct { - Value []byte -} - -// BytesValue is a wrapper for a byte slice -type BytesValue struct { - Value []byte -} - -// StringValue is a wrapper for a string -type StringValue struct { - Value string -} - -// BoolValue is a wrapper for a boolean -type BoolValue struct { - Value bool -} - -// OptionValue is a wrapper for an option value -type OptionValue struct { - Value any -} - -// Field is a field in a struct, enum etc. -type Field struct { - Name string - Value any -} - -// StructValue is a struct (collection of fields) -type StructValue struct { - Fields []Field -} - -// EnumValue is an enum (discriminant and fields) -type EnumValue struct { - Discriminant uint8 - Fields []Field -} - -// InputListValue is a list of values (used for encoding) -type InputListValue struct { - Items []any -} - -// OutputListValue is a list of values (used for decoding) -type OutputListValue struct { - Items []any - ItemCreator func() any -}