<div dir="ltr"><div dir="auto"><div><div class="gmail_extra"><div class="gmail_quote">On Jan 20, 2017 12:48 PM, "Elizabeth Myers" <<a href="mailto:elizabeth@interlinked.me" target="_blank">elizabeth@interlinked.me</a>> wrote:<br type="attribution"><blockquote class="gmail-m_5936344126949848725gmail-m_-2481568708881392823quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail-m_5936344126949848725gmail-m_-2481568708881392823quoted-text">On 20/01/17 10:59, Paul Moore wrote:<br>
> On 20 January 2017 at 16:51, Elizabeth Myers <<a href="mailto:elizabeth@interlinked.me" target="_blank">elizabeth@interlinked.me</a>> wrote:<br>
>> Should I write up a PEP about this? I am not sure if it's justified or<br>
>> not. It's 3 changes (calcsize and two format specifiers), but it might<br>
>> be useful to codify it.<br>
><br>
> It feels a bit minor to need a PEP, but having said that did you pick<br>
> up on the comment about needing to return the number of bytes<br>
> consumed?<br>
><br>
> str = struct.unpack('z', b'test\0xxx')<br>
><br>
> How do we know where the unpack got to, so that we can continue<br>
> parsing from there? It seems a bit wasteful to have to scan the string<br>
> twice to use calcsize for this...<br>
><br>
> A PEP (or at least, a PEP-style design document) might capture the<br>
> answer to questions like this. OTOH, the tracker discussion could<br>
> easily be enough - can you put a reference to the bug report here?<br>
><br>
> Paul<br>
><br>
<br>
</div>Two things:<br>
<br>
1) struct.unpack and struct.unpack_from should remain<br>
backwards-compatible. I don't want to return extra values from it like<br>
(length unpacked, (data...)) for that reason. If the calcsize solution<br>
feels a bit weird (it isn't much less efficient, because strings store<br>
their length with them, so it's constant-time), there could also be new<br>
functions that *do* return the length if you need it. To me though, this<br>
feels like a use case for struct.iter_unpack.<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">iter_unpack is strictly less powerful - you can easily and efficiently implement iter_unpack using unpack_from_with_offset (probably not it's real name, but you get the idea). The reverse is not true.</div><div dir="auto"><br></div><div dir="auto">And:</div><div dir="auto"><br></div><div dir="auto">val, offset = somefunc(buffer, offset)</div><div dir="auto"><br></div><div dir="auto">is *the* idiomatic signature for functions for unpacking complex binary formats. I've seen it reinvented independently at least 4 times in real projects. (It turns out that implementing sleb128 encoding in Python is sufficiently frustrating that you end up making lots of attempts to find someone anyone who has already done it. Or at least, I did :-).)<br><br></div><div>Here's an example of this idiom used to parse Mach-O binding tables, which iter_unpack definitely can't do:<br></div><div>  <a href="https://github.com/njsmith/machomachomangler/blob/master/machomachomangler/macho.py#L374-L429" target="_blank">https://github.com/njsmith/<wbr>machomachomangler/blob/master/<wbr>machomachomangler/macho.py#<wbr>L374-L429</a><br></div><div>Actually this example is a bit extreme since the format is *all* variable-width stuff, but it gives the idea. There are also lots of formats that have a mix of struct-style fixed width and variable width fields in a complicated pattern, e.g.:<br>  <a href="https://zs.readthedocs.io/en/latest/format.html#layout-details" target="_blank">https://zs.readthedocs.io/en/<wbr>latest/format.html#layout-<wbr>details</a><br></div><br><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail-m_5936344126949848725gmail-m_-2481568708881392823quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Definitely would prefer to avoid a bikeshed here, though other<br>
improvements to the struct module are certainly welcome!<br></blockquote><br></div><div class="gmail_quote">It doesn't necessarily have to be part of the same change, but if struct is gaining the infrastructure to support variable-width layouts then adding uleb128/sleb128 format specifiers would make a lot of sense. Implementing them in pure Python is difficult (all the standard "how to en/decode u/sleb128" documentation assumes you're working with C-style modulo integers) and slow, and they turn up all over the place: both of those links above, in Google protobufs, as a primitive in the .Net equivalent of the struct module [1], etc. <br><br></div><div class="gmail_quote">-n<br><br>[1] <a href="https://msdn.microsoft.com/en-us/library/system.io.binarywriter.write7bitencodedint.aspx">https://msdn.microsoft.com/en-us/library/system.io.binarywriter.write7bitencodedint.aspx</a></div></div></div></div>
</div>