Skip to content

Commit

Permalink
simplify depolorizer unpacking and null checks
Browse files Browse the repository at this point in the history
- resolves #40
- added a new method IsNull on Depolorizer to check if the next element on the wire is a WireNull
- modified the DepolorizePacked method to return IncompatibleWire when encountering WireNull instead of ErrNullPack
- removed the ErrNullPack error type
- added a new method Unpacked on Depolorizer that is direct wrapper on DepolorizePacked for aesthetics and to be consistent by acting as a mirror to the Packed method on Polorizer
-
  • Loading branch information
sarvalabs-manish committed Oct 25, 2024
1 parent 313c612 commit 5a50c26
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 32 deletions.
38 changes: 33 additions & 5 deletions depolorizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ func newLoadDepolorizer(data readbuffer, config *wireConfig) (*Depolorizer, erro
return &Depolorizer{pack: pack, packed: true, cfg: *config}, nil
}

// Unpacked attempts to unpack a Depolorizer that contains a WirePack or WireDoc element.
// A new Depolorizer is returned with the unpacked wire and the original Depolorizer consumes one wire element.
// Returns an error if there are no elements left or if the element is not a WirePack or WireDoc.
//
// note: this method is a wrapper around DepolorizePacked for brevity and aesthetics.
func (depolorizer *Depolorizer) Unpacked() (*Depolorizer, error) {
return depolorizer.DepolorizePacked()
}

// Done returns whether all elements in the Depolorizer have been read.
func (depolorizer *Depolorizer) Done() bool {
// Check if packbuffer is done if in packed mode
Expand All @@ -70,6 +79,28 @@ func (depolorizer *Depolorizer) Done() bool {
return depolorizer.done
}

// IsNull returns whether the next element in the Depolorizer is a WireNull without
// consuming it from the buffer. False if there are no elements left in the Depolorizer.
//
// Use DepolorizeNull to consume the WireNull element if further elements are to be read.
func (depolorizer *Depolorizer) IsNull() bool {
// Check if the Depolorizer is in packed mode
if !depolorizer.packed {
// Return the nullity of the atomic buffer
return depolorizer.data.wire.IsNull()
}

// Peek the next element from the packbuffer.
// Errors if there are no elements left
peek, ok := depolorizer.pack.peek()
if !ok {
return false
}

// Return the nullity of the peeked element
return peek.IsNull()
}

// Depolorize decodes a value from the Depolorizer.
// Decodes the data in the wire into the given object using Go reflection.
// Returns an error if the object is not a pointer or if a decode error occurs.
Expand Down Expand Up @@ -278,8 +309,8 @@ func (depolorizer *Depolorizer) DepolorizeRaw() (Raw, error) {
}

// DepolorizePacked attempts to decode another Depolorizer from the Depolorizer, consuming one wire element.
// A new Depolorizer is returned with the unpacked wire if the element is WirePack or WireDoc.
// Returns an error if there are no elements left or if the element is not WirePack or WireDoc.
// Returns a ErrNullPack if the element is a WireNull.
func (depolorizer *Depolorizer) DepolorizePacked() (*Depolorizer, error) {
// Read the next element
data, err := depolorizer.read()
Expand All @@ -291,11 +322,8 @@ func (depolorizer *Depolorizer) DepolorizePacked() (*Depolorizer, error) {
case WirePack, WireDoc:
return newLoadDepolorizer(data, &depolorizer.cfg)

case WireNull:
return nil, ErrNullPack

default:
return nil, IncompatibleWireType(data.wire, WireNull, WirePack, WireDoc)
return nil, IncompatibleWireType(data.wire, WirePack, WireDoc)
}
}

Expand Down
4 changes: 2 additions & 2 deletions depolorizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,15 +380,15 @@ func TestDepolorizer_DepolorizePacked(t *testing.T) {
require.Nil(t, err)

_, err = depolorizer.DepolorizePacked()
assert.EqualError(t, err, ErrNullPack.Error())
assert.EqualError(t, err, "incompatible wire: unexpected wiretype 'null'. expected one of: {pack, document}")
})

t.Run("Incompatible", func(t *testing.T) {
depolorizer, err := NewDepolorizer([]byte{3, 1, 44})
require.Nil(t, err)

_, err = depolorizer.DepolorizePacked()
assert.EqualError(t, err, "incompatible wire: unexpected wiretype 'posint'. expected one of: {null, pack, document}")
assert.EqualError(t, err, "incompatible wire: unexpected wiretype 'posint'. expected one of: {pack, document}")
})
}

Expand Down
2 changes: 0 additions & 2 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ var (
// It acts a signal for error and value handlers.
errNilValue = errors.New("nil value")

// ErrNullPack is an error for when a WireNull is attempted to be converted to a Depolorizer
ErrNullPack = errors.New("null pack element")
// ErrObjectNotPtr is an error for when a non pointer object is passed to the Depolorize function
ErrObjectNotPtr = errors.New("object not a pointer")
// ErrObjectNotSettable is an error for when a non-settable pointer is passed to the Depolorize function
Expand Down
51 changes: 28 additions & 23 deletions polo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1623,20 +1623,18 @@ func (object CustomEncodeObject) Polorize() (*Polorizer, error) {
polorizer.PolorizeString(object.A)
polorizer.PolorizeInt(int64(object.B))

if object.C == nil {
polorizer.PolorizeNull()
} else {
if object.C != nil {
C := NewPolorizer()
for _, elem := range object.C {
C.PolorizeString(elem)
}

polorizer.PolorizePacked(C)
} else {
polorizer.PolorizeNull()
}

if object.D == nil {
polorizer.PolorizeNull()
} else {
if object.D != nil {
keys := make([]string, 0, len(object.D))
for key := range object.D {
keys = append(keys, key)
Expand All @@ -1650,6 +1648,8 @@ func (object CustomEncodeObject) Polorize() (*Polorizer, error) {
}

polorizer.PolorizePacked(D)
} else {
polorizer.PolorizeNull()
}

polorizer.PolorizeFloat64(object.E)
Expand All @@ -1658,10 +1658,12 @@ func (object CustomEncodeObject) Polorize() (*Polorizer, error) {
}

func (object *CustomEncodeObject) Depolorize(depolorizer *Depolorizer) (err error) {
depolorizer, err = depolorizer.DepolorizePacked()
if errors.Is(err, ErrNullPack) {
if depolorizer.IsNull() {
return nil
} else if err != nil {
}

depolorizer, err = depolorizer.Unpacked()
if err != nil {
return err
}

Expand All @@ -1670,21 +1672,23 @@ func (object *CustomEncodeObject) Depolorize(depolorizer *Depolorizer) (err erro
return err
}

// todo: cleanup with extended decode methods
B, err := depolorizer.DepolorizeInt()
if err != nil {
return err
}

object.B = int32(B)

c, err := depolorizer.DepolorizePacked()

switch {
case errors.Is(err, ErrNullPack):
if depolorizer.IsNull() {
object.C = nil
case err != nil:
return err
default:
_ = depolorizer.DepolorizeNull()
} else {
c, err := depolorizer.DepolorizePacked()
if err != nil {
return err
}

object.C = make([]string, 0, 5)

for !c.Done() {
Expand All @@ -1697,14 +1701,15 @@ func (object *CustomEncodeObject) Depolorize(depolorizer *Depolorizer) (err erro
}
}

d, err := depolorizer.DepolorizePacked()

switch {
case errors.Is(err, ErrNullPack):
if depolorizer.IsNull() {
object.D = nil
case err != nil:
return err
default:
_ = depolorizer.DepolorizeNull()
} else {
d, err := depolorizer.DepolorizePacked()
if err != nil {
return err
}

object.D = make(map[string]string)

for !d.Done() {
Expand Down

0 comments on commit 5a50c26

Please sign in to comment.