rybakit / msgpack.php

A pure PHP implementation of the MessagePack serialization format / msgpack.org[PHP]
MIT License
388 stars 18 forks source link

Add seek/pos to buffer unpacker #26

Closed sskaje closed 6 years ago

sskaje commented 6 years ago

In my case, I got a buff, which has several msgpack-ed parts.

So I added seek/pos to my fork, and I write a simple script like:

<?php
    $unpacker = new BufferUnpacker($content);
    $unpacker->seek(4);

    while ($unpacker->pos() >= 0) {
       $value = $unpacker->unpack();
        echo "=== Position=" . $unpacker->pos() . " ===\n";
        var_dump($value);
  }

I was considering add a fseek() like seek(), but feeling not very useful to me, so I just added a simple one.

rybakit commented 6 years ago

In my case, I got a buff, which has several msgpack-ed parts.

I wonder if tryUnpack() would work for your use case? I implemented seeking functionality time ago (check this and this), but removed later as I didn't find a use case for it.

sskaje commented 6 years ago

@rybakit IMO tryUnpack() works for: 1 streaming and then unpack 2 test for unknown structure

My case looks like

| Packed ID, int32 BE | Command Byte | Flags Byte | Length, int16 BE | | msgpack data ...|

It's a known structure, tryUnpack() is not a good choice for me. Without fseek() like function, I need to $unpacker->unpack(substr($raw_packet, $offset)) If there are many segments of msgpacked data, with known structure, tryUnpack() is not a good choice.

rybakit commented 6 years ago

@sskaje OK, adding seek() makes sense then, but I'm not sure about pos(). Looking at your example, I do not see how that loop can be terminated, pos() will never return -1 until you put seek() inside the loop. From the other hand, I guess

$parts = $unpacker->seek(4)->tryUnpack();

will do the trick. Am I correct?

sskaje commented 6 years ago

@rybakit You're right, I'll let seek returns $this and remove pos()

rybakit commented 6 years ago

@sskaje I've fixed CS issues, added tests and seek origin argument to seek(): https://github.com/rybakit/msgpack.php/commit/0d2818c7121e669952cbaa5437bbeebff2af9743#diff-2a07a1ef20556a8548b7b52903182b2f.

rybakit commented 6 years ago

And the final version: https://github.com/rybakit/msgpack.php/blob/2c2f046ad6f2cc013770487517eaa99a6fec102a/src/BufferUnpacker.php#L73-L99

sskaje commented 6 years ago

I just came back from vacation. You did a very good job, thank you.