Skip to content

Commit

Permalink
[bcs] Add optional serialization helper function
Browse files Browse the repository at this point in the history
  • Loading branch information
gregnazario committed Nov 12, 2024
1 parent c3a2a2a commit 2405159
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to the Aptos Go SDK will be captured in this file. This chan
adheres to the format set out by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

# Unreleased
- Add BCS support for optional values

# v1.1.0 (11/07/2024)
- Add icon uri and project uri to FA client, reduce duplicated code
Expand Down
26 changes: 26 additions & 0 deletions bcs/bcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,32 @@ func Test_ConvenienceFunctions(t *testing.T) {
assert.Equal(t, []byte{0x01, 0x05}, serializedBytes)
}

func Test_SerializeOptional(t *testing.T) {
ser := Serializer{}
someValue := uint8(0xFF)
SerializeOption(&ser, &someValue, func(ser *Serializer, val uint8) {
ser.U8(val)
})
assert.Equal(t, []byte{0x01, 0xFF}, ser.ToBytes())
des := NewDeserializer(ser.ToBytes())
desValue := DeserializeOption(des, func(des *Deserializer, out *uint8) {
*out = des.U8()
})
assert.Equal(t, &someValue, desValue)

ser2 := Serializer{}
SerializeOption(&ser2, nil, func(ser *Serializer, val uint8) {
ser.U8(val)
})
assert.Equal(t, []byte{0x00}, ser2.ToBytes())

des2 := NewDeserializer(ser2.ToBytes())
desValue2 := DeserializeOption(des2, func(des *Deserializer, out *uint8) {
*out = des.U8()
})
assert.Nil(t, desValue2)
}

func Test_NilStructs(t *testing.T) {
ser := Serializer{}
ser.Struct(nil)
Expand Down
36 changes: 36 additions & 0 deletions bcs/deserializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,42 @@ func DeserializeSequenceWithFunction[T any](des *Deserializer, deserialize func(
return out
}

// DeserializeOption deserializes an optional value
//
// # Under the hood, this is represented as a 0 or 1 length array
//
// Here's an example for handling an optional value:
//
// // For a Some(10) value
// bytes == []byte{0x01, 0x0A}
// des := NewDeserializer(bytes)
// output := DeserializeOption(des, nil, func(des *Deserializer, out *uint8) {
// out = des.U8()
// })
// // output == &10
//
// // For a None value
// bytes2 == []byte{0x00}
// des2 := NewDeserializer(bytes2)
// output := DeserializeOption(des2, nil, func(des *Deserializer, out *uint8) {
// out = des.U8()
// })
// // output == nil
func DeserializeOption[T any](des *Deserializer, deserialize func(des *Deserializer, out *T)) *T {
array := DeserializeSequenceWithFunction(des, deserialize)
switch len(array) {
case 0:
// None
return nil
case 1:
// Some
return &array[0]
default:
des.setError("expected 0 or 1 element as an option, got %d", len(array))
}
return nil
}

// setError overrides the previous error, this can only be called from within the bcs package
func (des *Deserializer) setError(msg string, args ...any) {
if des.err != nil {
Expand Down
28 changes: 28 additions & 0 deletions bcs/serializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,31 @@ func SerializeSingle(marshal func(ser *Serializer)) (bytes []byte, err error) {
bytes = ser.ToBytes()
return bytes, nil
}

// SerializeOption serializes an optional value
//
// # Under the hood, this is represented as a 0 or 1 length array
//
// Here's an example for handling an optional value:
//
// // For a Some(10) value
// input := uint8(10)
// ser := &Serializer{}
// bytes, _ := SerializeOption(ser, &input, func(ser *Serializer, item uint8) {
// ser.U8(item)
// })
// // bytes == []byte{0x01,0x0A}
//
// // For a None value
// ser2 := &Serializer{}
// bytes2, _ := SerializeOption(ser2, nil, func(ser *Serializer, item uint8) {
// ser.U8(item)
// })
// // bytes2 == []byte{0x00}
func SerializeOption[T any](ser *Serializer, input *T, serialize func(ser *Serializer, item T)) {
if input == nil {
SerializeSequenceWithFunction([]T{}, ser, serialize)
} else {
SerializeSequenceWithFunction([]T{*input}, ser, serialize)
}
}

0 comments on commit 2405159

Please sign in to comment.